C#中的curl-F等价物

我试图在C#中使用HTTPClient对象向API发送一个post请求。 这是CURL命令:

curl -X POST https://zzz.zzz.zzz/yyy -F Key=abcd -F media=@"audio.aac" 

我写了以下代码:

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Net.Http; using System.IO; using System.Net.Http.Headers; namespace Speech2Text { class Program { static void Main(string[] args) { curl().Wait(); } static async Task curl() { var client = new HttpClient(); //Create List of KeyValuePairs List<KeyValuePair> bodyProperties = new List<KeyValuePair>(); bodyProperties.Add(new KeyValuePair("key", "abcd")); bodyProperties.Add(new KeyValuePair("media", "@audio.aac")); var dataContent = new FormUrlEncodedContent(bodyProperties.ToArray()); HttpResponseMessage response = await client.PostAsync("https://zzz.zzz.zzz/yyy", dataContent); HttpContent responseContent = response.Content; using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync())) { Console.WriteLine(await reader.ReadToEndAsync()); } } } } 

但我一直这样说:

 {"code":400,"message":"Please use [media] for the media file field name in your POST request."} 

dataContect变量中是否有任何问题,或者是其他问题?

发送POST时,发送给服务器的Content-Type确实是服务器期望的内容类型非常重要。 您可以使用curl中的-trace选项轻松validation发送的内容:

 curl -v --trace - -X POST http://localhost -F Key=abcd -F media=@"image.txt" 

当你运行它时,你会发现前几行的某个地方:

 00b0: 63 6f 6e 74 69 6e 75 65 0d 0a 43 6f 6e 74 65 6e continue..Conten 00c0: 74 2d 54 79 70 65 3a 20 6d 75 6c 74 69 70 61 72 t-Type: multipar 00d0: 74 2f 66 6f 72 6d 2d 64 61 74 61 3b 20 62 6f 75 t/form-data; bou 00e0: 6e 64 61 72 79 3d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d ndary=---------- 00f0: 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d 2d ---------------- 0100: 2d 2d 61 61 62 64 66 31 66 66 38 35 66 66 0d 0a --aabdf1ff85ff.. 0110: 0d 0a .. 

所以curl正在发送一个内容类型的multipart/form-data;

在您的代码中,您使用FormUrlEncodedContent类, FormUrlEncodedContent在其描述中指出:

使用application / x-www-form-urlencoded MIME类型编码的名称/值元组的容器。

所以这不是正确的Conent-Type。

更好的匹配是MultipartFormDataContent因为它指出:

为使用multipart / form-data MIME类型编码的内容提供容器。

找到正确的类后,我们只需要构建容器:

 var dataContent = new MultipartFormDataContent(); var keyValue = new ByteArrayContent( Encoding.ASCII.GetBytes("abcd") ); dataContent.Add(keyValue, "key"); using (var client = new HttpClient()) { // open your file using (var fs = File.OpenRead(@"c:\path\to\audio.acc")) { // create StreamContent from the file var fileValue = new StreamContent(fs); // add the name and meta-data dataContent.Add(fileValue, "media", "audio.acc"); HttpResponseMessage response = await client.PostAsync( "http://yoursite.org", dataContent); HttpContent responseContent = response.Content; using (var reader = new StreamReader(await responseContent.ReadAsStreamAsync())) { Console.WriteLine(await reader.ReadToEndAsync()); } } } 

运行此代码在Fiddler中显示:

 POST / HTTP/1.1 Content-Type: multipart/form-data; boundary="f7335f00-bc16-4518-ae7a-149491403792" Host: yoursite.org Content-Length: 1014 Expect: 100-continue Connection: Keep-Alive --f7335f00-bc16-4518-ae7a-149491403792 Content-Disposition: form-data; name=key abcd --f7335f00-bc16-4518-ae7a-149491403792 Content-Disposition: form-data; name=media; filename=audio.acc; filename*=utf-8''audio.acc 

这更符合curl的跟踪输出。