【问题标题】:Posting `multipart/form-data` with Flurl使用 Flurl 发布“multipart/form-data”
【发布时间】:2016-08-18 10:34:50
【问题描述】:

我需要发布以下请求:

POST http://target-host.com/some/endpoint HTTP/1.1
Content-Type: multipart/form-data; boundary="2e3956ac-de47-4cad-90df-05199a7c1f53"
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Content-Length: 6971
Host: target-host.com

--2e3956ac-de47-4cad-90df-05199a7c1f53
Content-Disposition: form-data; name="some-label"

value
--2e3956ac-de47-4cad-90df-05199a7c1f53
Content-Disposition: form-data; name="file"; filename="my-filename.txt"

<file contents>
--2e3956ac-de47-4cad-90df-05199a7c1f53--

我可以使用 Python requests 库非常轻松地做到这一点,如下所示:

import requests

with open("some_file", "rb") as f:
    byte_string = f.read()

requests.post(
    "http://target-host.com/some/endpoint",
    data={"some-label": "value"},
    files={"file": ("my-filename.txt", byte_string)})

有没有办法对Flurl.Http 库做同样的事情?

我对@9​​87654321@ 的做法的问题是它会为每个键值对插入Content-Type 标头,它会为文件数据插入filename*=utf-8'' 标头。但是,我尝试将请求发布到的服务器不支持这一点。还要注意标题中 namefilename 值周围的双引号。

编辑:下面是我使用Flurl.Http 发出帖子请求的代码:

using System.IO;
using Flurl;
using Flurl.Http;

namespace ConsoleApplication
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var fs = File.OpenRead("some_file");

            var response = "http://target-host.com"
                .AppendPathSegment("some/endpoint")
                .PostMultipartAsync(mp => mp
                    .AddString("some-label", "value")
                    .AddFile("file", fs, "my-filename.txt")
                ).Result;
        }
    }
}

【问题讨论】:

  • 这是一个非常合理的编程问题。投票关闭它的人可以解释一下吗?
  • 你是说在文件数据的头部包含filename*实际上导致调用失败?

标签: c# post multipartform-data flurl


【解决方案1】:

根据spec(日期为 2011 年 6 月),建议同时发送 filenamefilename* 以获得最大兼容性:

许多早于本规范的用户代理实现都没有 了解“文件名*”参数。因此,当两个“文件名” 和“文件名*”存在于单个标头字段值中,收件人 应该选择“文件名*”并忽略“文件名”。这样,发件人可以 避免特殊情况下的特定用户代理发送更多 富有表现力的“filename*”参数,而“filename”参数为 旧收件人的后备。

如果filename* 确实导致调用失败,那么服务器遵守HTTP 规范确实存在问题。此外,将namefilename 括在引号中是非常不标准的。

也就是说,Flurl 的快捷方式涵盖了 90% 的情况,但您始终可以使用底层的 HttpClient API 来涵盖此类不寻常的情况。在这种情况下,我认为您需要手动构建内容,以便处理那些 Content-Disposition 标头:

var mpc = new MultipartContent();
var sc = new StringContent("value");
sc.Headers.Add("Content-Disposition", "form-data; name=\"some-label\"");
mpc.Add(sc);
var fc = new StreamContent(fs);
fc.Headers.Add("Content-Disposition", "form-data; name=\"file\"; filename=\"my-filename.txt\"");
mpc.Add(fc);

然后你可以像这样与 Flurl 一起使用它:

var response = await "http://target-host.com"....PostAsync(mpc);

【讨论】:

  • 我发现一个应用程序 (Minio) 如果非文件字段有 content-type 会失败。可能不是唯一的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-31
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 2018-12-31
相关资源
最近更新 更多