2016-08-16 70 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);