通过请求发送 multipart/form-data post 的区别

Differences in sending a multipart/form-data post via requests

我在尝试 post 将文件发送到服务器时遇到问题。我正在尝试制作文件上传脚本到服务器,这个服务器非常'Sensitive to correctness post request'

我调试了将文件发送到服务器的页面,浏览器发送了这个 (TextView):

POST http://example.com/post HTTP/1.1
Host: example.com
Connection: keep-alive
Content-Length: 20625
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarykGHBkXoER9gNuVna
Referer: http://example.com/foo
Accept-Encoding: gzip, deflate
Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4,pt;q=0.2

------WebKitFormBoundarykGHBkXoER9gNuVna
Content-Disposition: form-data; name="files[]"; filename="file.zip"
Content-Type: application/octet-stream

...raw file data...

------WebKitFormBoundarykGHBkXoER9gNuVna--

但是,我的脚本正在发送这个 (TextView):

POST http://example.com/post HTTP/1.1
Host: example.com
Connection: keep-alive
Accept-Encoding: gzip, deflate
Accept: */*
User-Agent: python-requests/2.18.1
Content-Length: 20604

--f8c266cf436941019c5a80c7d4779a57
Content-Disposition: form-data; name="files[]"; filename="file.zip"
Content-Type: application/zip

...raw file data...

--f8c266cf436941019c5a80c7d4779a57--

在服务器上导致错误,附加说明:当我将 files=files 更改为 data=files

时,此错误开始

当前代码:

files = MultipartEncoder({'files[]': (filename, open(local_path,'rb'), mimetype)})
UploadFile = requests.post(self.UploadURL, data=files, allow_redirects=False)

工作代码:

files = {'files[]': (filename, open(local_path,'rb'), mimetype)}
UploadFile = requests.post(self.UploadURL, files=files, allow_redirects=False)

我正在使用 MultipartEncoder 来允许发送大文件。 我看到最大的不匹配是 "boundary",但为什么这个 'boundary' 在 working code 中生成但在 Current code 中没有生成?

如何解决?

您没有设置 Content-Type header,MultipartEncoder 为您提供:

files = MultipartEncoder({'files[]': (filename, open(local_path,'rb'), mimetype)})
UploadFile = requests.post(
    self.UploadURL, data=files, allow_redirects=False,
    headers={'Content-Type': files.content_type})

header必须来自multi-part编码,因为它负责挑选边界用于划分multipart中的各个MIME部分回复。在您上传的内容中:

--f8c266cf436941019c5a80c7d4779a57

但它是在您的代码每次运行时随机生成的。提供的 header 看起来像:

Content-Type: multipart/form-data; boundary=--f8c266cf436941019c5a80c7d4779a57