2016-08-16 52 views
2

我需要张贴下列要求:发布`多部分/形式data`与Flurl

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库做同样的事情?

我的documented这样做的问题是,它会为每个键值对插入Content-Type标题,并且它会为文件数据插入filename*=utf-8''标题。但是,我试图发布请求的服务器不支持此操作。还要注意标题中的namefilename值附近的双引号。

编辑:下面是我用来做与Flurl.Http POST请求的代码:

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; 
     } 
    } 
} 
+0

这是一个非常合法的编程问题。谁可以投票结束,请解释一下? –

+0

你是说在文件头中包含'filename *'实际上导致了调用失败? –

回答

2

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

早于本规范的许多用户代理实现不了解“文件名*”参数 。因此,当“文件名” 和“文件名*”都出现在单个标题字段值中时,收件人 应该选择“文件名*”并忽略“文件名”。通过这种方式,发件人可以通过发送更多 富有表现力的“文件名*”参数和“文件名”参数作为 回退给旧版收件人,从而避免特殊大小的特定用户代理。

如果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);