10

我们正在尝试用python(使用python-requests atm)编写一个脚本来向内容必须是MultipartFormData的站点发出POST请求。当我们手动执行此 POST 请求时(通过填写网站上的表格并发布),使用wireshark,出现了(短版):

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

当我们尝试使用 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

奇怪的是,数据包的“一般类型”确实是多部分/表单数据,但是发送的单个项目(key = 'name', value='John Doe')的类型为 application/x-pandoplugin(随机我猜我的电脑上的应用程序)。

这是使用的代码:

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

有没有办法指定单个项目的内容类型而不是使用 headers 参数(它只会改变“整个”数据包的类型)?

我们认为服务器无法正确响应是因为它无法理解我们发送的内容类型。

小更新: 我认为多部分内容的不同部分现在与我在浏览器中执行 POST 时发送的部分相同,所以这很好。服务器实际上并没有做我用脚本发送的更改。唯一不同的是不同部分的顺序。

例如,这是我的浏览器发送的内容:

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)

这就是脚本(使用 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)

服务器是否有可能依赖零件的顺序?根据分段上传表格:订单有保证吗?,显然是?如果是这样,是否可以使用 requests 库显式强制订单?在这种情况下更糟的是:文件和文本值混合在一起。

因此,强制执行命令似乎相当困难。这是我目前的做法:

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

EDIT2: 我在请求插件中进行了修改,以确保部件的顺序与原始请求中的相同。这并不能解决问题,所以我想我的问题没有直接的解决方案。我会向网站的开发人员发送邮件,希望他们能帮助我!

4

3 回答 3

8

您的代码看起来正确。

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

...并且应该发送一个“multipart/form-data”帖子。

事实上,我收到了这样的帖子:

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--

知道你为什么会得到那个奇怪的 Content-Type 标头:

Content-Type: application/x-pandoplugin

我将首先从您的机器中完全删除 Pando Web 插件,然后再次尝试您的 python-requests 代码。(或从不同的机器尝试)

于 2013-08-07T13:36:32.203 回答
2

从今天开始,您可以:

response = s.post('http://url.com', files={'name': (filename, contents, content_type)})
于 2016-11-14T04:01:12.300 回答
0

Python 使用系统范围的配置文件来“猜测”文件的 mime 类型。如果这些插件正在使用他们的自定义 mime 类型注册您的文件扩展名,那么您最终会将其放入。

最安全的方法是进行适合您发送的特定服务器的自己的 mime 类型猜测,并且只对您没有想到的扩展使用本机 python mime 类型猜测。

我不知道您如何使用 python-requests 手动指定内容类型,但我希望它应该是可能的。

于 2013-11-20T19:24:22.387 回答