简体   繁体   English

使用Multipart / form-data的POST请求。内容类型不正确

[英]POST request with Multipart/form-data. Content-type not correct

We're trying to write a script with python (using python-requests atm) to do a POST request to a site where the content has to be MultipartFormData. 我们正在尝试用python编写一个脚本(使用python-requests atm)来对内容必须是MultipartFormData的站点发出POST请求。 When we do this POST request manually (by filling in the form on the site and post), using wireshark, this came up (short version): 当我们手动执行此POST请求时(通过填写网站上的表单并发布),使用wireshark,这就出现了(简短版本):

Content-Type: multipart/form-data;
Content-Disposition: form-data; name="name"
Data (8 Bytes)
    John Doe

When we try to use the python-requests library for achieving the same result, this is sent: 当我们尝试使用python-requests库来实现相同的结果时,会发送:

Content-Type: application/x-pandoplugin
Content-Disposition: form-data; name="name"; filename="name"\r\n
Media type: application/x-pandoplugin (12 Bytes)
    //and then in this piece is what we posted://
    John Doe

The weird thing is that the 'general type' of the packet indeed is multipart/form-data, but the individual item sent (key = 'name', value= 'John Doe') has type application/x-pandoplugin (a random application on my pc I guess). 奇怪的是,数据包的“常规类型”确实是多部分/表单数据,但发送的单个项目(key ='name',value ='John Doe')具有类型application / x-pandoplugin(随机应用在我的电脑上我猜)。

This is the code used: 这是使用的代码:

response = s.post('http://url.com', files={'name': 'John Doe'})

Is there a way to specify the content-type of the individual items instead of using the headers argument (which only changes the type of the 'whole' packet)? 有没有办法指定单个项的内容类型而不是使用headers参数(只更改'整个'数据包的类型)?

We think the server doesn't respond correctly due to the fact that it can't understand the content-type we send it. 我们认为服务器没有正确响应,因为它无法理解我们发送它的内容类型。

Little update: I think the different parts of the multipart content are now identical to the ones sent if I do the POST in the browser, so that's good. 小更新:我认为多部分内容的不同部分现在与我在浏览器中执行POST时发送的部分相同,所以这很好。 Still the server doesn't actually do the changes I send it with the script. 服务器实际上并没有执行我用脚本发送的更改。 The only thing that still is different is the order of the different parts. 唯一不同的是不同部分的顺序。

For example this is what my browser sends: 例如,这是我的浏览器发送的内容:

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part:  (text/plain)
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n
    Content-Type: text/plain\r\n\r\n
    Line-based text data: text/plain
        lore ipsum blabbla

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n
    Data (2 bytes)

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n
    Data (2 bytes)

And this is what the script (using python-requests) sends: 这就是脚本(使用python-requests)发送的内容:

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n
    Data (2 bytes)

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part:  (text/plain)
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n
    Content-Type: text/plain\r\n\r\n
    Line-based text data: text/plain
        lore ipsum blabbla

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n
    Data (2 bytes)

Could it be possible that the server counts on the order of the parts? 服务器是否可能依赖于部件的顺序? According to Multipart upload form: Is order guaranteed? 根据Multipart上传表格:订单有保证吗? , it apparently is? ,它显然是? And if so, is it possible to explicitly force an order using the requests library? 如果是这样,是否可以使用请求库明确强制执行订单? And to make things worse in that case: There is a mixture of a file and just text values. 并且在这种情况下使事情变得更糟:文件和文本值混合在一起。

So forcing an order seems rather difficult. 所以强迫订单似乎相当困难。 This is the current way I do it: 这是我目前的做法:

s.post('http://www.url.com', files=files,data = form_values)

EDIT2: I did a modification in the requests plugin to make sure the order of the parts is the same as in the original request. EDIT2:我在请求插件中做了一个修改,以确保部件的顺序与原始请求中的顺序相同。 This doesn't fix the problem so I guess there is no straightforward solution for my problem. 这不能解决问题所以我想我的问题没有直接的解决方案。 I'll send a mail to the devs of the site and hope they can help me! 我会发送邮件给网站的开发者,希望他们能帮助我!

your code looks correct. 你的代码看起来正确。

requests.post('http://url.com', files={'name': 'John Doe'})

... and should send a 'multipart/form-data' Post. ......并且应该发送'multipart / form-data'帖子。

and indeed, I get something like this posted: 事实上,我发布了这样的内容:

Accept-Encoding: gzip, deflate, compress
Connection: close
Accept: */*
Content-Length: 188
Content-Type: multipart/form-data; boundary=032a1ab685934650abbe059cb45d6ff3
User-Agent: python-requests/1.2.3 CPython/2.7.4 Linux/3.8.0-27-generic

--032a1ab685934650abbe059cb45d6ff3
Content-Disposition: form-data; name="name"; filename="name"
Content-Type: application/octet-stream

John Doe
--032a1ab685934650abbe059cb45d6ff3--

I have no idea why you'd get that weird Content-Type header: 知道为什么你会得到那个奇怪的Content-Type标题:

Content-Type: application/x-pandoplugin

I would begin by removing Pando Web Plugin from your machine completely, and then try your python-requests code again. 我首先从你的机器上完全删除Pando Web插件,然后再次尝试你的python请求代码。 (or try from a different machine) (或尝试从不同的机器)

截至今天你可以做到:

response = s.post('http://url.com', files={'name': (filename, contents, content_type)})

Python uses a system-wide configuration file to "guess" the mime-type of a file. Python使用系统范围的配置文件来“猜测”文件的mime类型。 If those plugins are registering your file extension with their custom mime-type you'll end up putting that in instead. 如果这些插件正在使用他们的自定义mime类型注册您的文件扩展名,那么您最终会将其放入。

The safest approach is make your own mime type guessing that suits the particular server you're sending do, and only use the native python mime type guessing for extensions you didn't think of. 最安全的方法是使你自己的mime类型猜测适合你发送的特定服务器,并且只使用本机python mime类型猜测你没想到的扩展。

How exactly you specify the content-type manually with python-requests I don't know, but I expect it should be possible. 你究竟用python请求手动指定内容类型我不知道,但我希望它应该是可能的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在显示 KeyError 但在删除时显示成功消息的 POST 请求的标头上添加“Content-Type”:“multipart/form-data” - Adding "Content-Type": "multipart/form-data" on headers on a POST request showing KeyError but showing success message while removing it python 请求不将我的 POST 数据作为内容类型发送:multipart/form-data auto - python requests not sending my POST data as content-type:multipart/form-data auto Python请求,如何向multipart/form-data请求添加内容类型 - Python requests, how to add content-type to multipart/form-data request 在 Content-Type:multipart/form-data 的情况下,如何一次从 Flask 请求 object 获取多个图像? - How to get multiple images from Flask request object at once in case of Content-Type:multipart/form-data? Python Scrapy将内容类型覆盖为请求后的多部分/表单数据 - Python Scrapy override content type to be multipart/form-data on post Request Robotframework.request - 如何使用内容“multipart/form-data”和键值发出 POST 请求 - Robotframework.request - How to make a POST request with content “multipart/form-data” and a Key value Python multipart/form-data Post 请求 - Python multipart/form-data Post Request Robotframework.request - 如何使用内容“multipart / form-data”发出POST请求 - Robotframework.request - How to make a POST request with content “multipart/form-data” 烧瓶中没有POST请求和Content-Type“application / json”的响应 - No response with POST request and Content-Type “application/json” in flask 强制 Content-Type 或公开 Flask 中已知内容类型的 request.data - Force Content-Type or expose request.data in Flask for known content-type
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM