【问题标题】:Curl -F equivalent in C#C# 中的 curl -F 等效项
【发布时间】:2016-07-28 06:16:48
【问题描述】:

我正在尝试使用 C# 中的 HTTPClient 对象向 API 发送发布请求。 这是 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<string, string>> bodyProperties = new List<KeyValuePair<string, string>>();

        bodyProperties.Add(new KeyValuePair<string, string>("key", "abcd"));
        bodyProperties.Add(new KeyValuePair<string, string>("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 变量是否有任何问题或其他问题?

【问题讨论】:

  • @w0lf 感谢您的评论。我在上面的代码中使用了相同的方法,但我认为它没有捕获我传递给 HTTP 请求的参数。因为,在发送media参数的同时,它并不理解。
  • 问题出在服务器端,而不是客户端。你的代码没问题。你已经得到了 JSON 响应。
  • 尝试从“@audio.aac”中删除“@”
  • @x... 没用。这是我应该传递的文件的名称。它不应该是文件对象或类似的东西而不是字符串吗?
  • 当使用 curl 时,@ 会吞下文件的内容。您将不得不手动打开文件流并将其拉入字节数组或类似的东西

标签: c# curl http-post multipartform-data dotnet-httpclient


【解决方案1】:

发送 POST 时,发送到服务器的 Content-Type 确实是服务器期望的,这一点很重要。您可以使用curl 中的-trace 选项轻松验证发送的内容:

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 发送的 Content-Type 为 multipart/form-data;

在您的代码中,您使用 FormUrlEncodedContent 类,该类在其描述中声明:

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

所以这不是正确的内容类型。

更好的匹配是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 的跟踪输出。

【讨论】:

  • 感谢 Rene 的彻底解决方案。
猜你喜欢
  • 1970-01-01
  • 2014-02-28
  • 1970-01-01
  • 1970-01-01
  • 2011-01-10
  • 2011-10-12
  • 2010-09-12
  • 1970-01-01
  • 2018-10-31
相关资源
最近更新 更多