如何在python中发送多部分/表单数据请求?怎么发文件,我懂,但是怎么用这种方法发表单数据就不懂了。


当前回答

这是你需要上传一个大的单一文件作为多部分formdata的python片段。在服务器端运行NodeJs Multer中间件。

import requests
latest_file = 'path/to/file'
url = "http://httpbin.org/apiToUpload"
files = {'fieldName': open(latest_file, 'rb')}
r = requests.put(url, files=files)

对于服务器端,请检查multer文档:https://github.com/expressjs/multer 这里的字段single('fieldName')用于接受单个文件,如下所示:

var upload = multer().single('fieldName');

其他回答

基本上,如果你指定了一个files参数(一个字典),那么请求将发送一个多部分的/form-data POST,而不是application/x-www-form-urlencoded POST。你不局限于使用字典中的实际文件,但是:

>>> import requests
>>> response = requests.post('http://httpbin.org/post', files=dict(foo='bar'))
>>> response.status_code
200

httpbin.org让你知道你发布了什么头;在response.json()中我们有:

>>> from pprint import pprint
>>> pprint(response.json()['headers'])
{'Accept': '*/*',
 'Accept-Encoding': 'gzip, deflate',
 'Connection': 'close',
 'Content-Length': '141',
 'Content-Type': 'multipart/form-data; '
                 'boundary=c7cbfdd911b4e720f1dd8f479c50bc7f',
 'Host': 'httpbin.org',
 'User-Agent': 'python-requests/2.21.0'}

更好的是,通过使用元组而不是单个字符串或字节对象,您可以进一步控制每个部分的文件名、内容类型和额外的标题。元组应该包含2到4个元素;文件名、内容、可选的内容类型和可选的其他标头字典。

我将使用以None作为文件名的元组形式,这样filename="…"参数将从这些部分的请求中删除:

>>> files = {'foo': 'bar'}
>>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))
--bb3f05a247b43eede27a124ef8b968c5
Content-Disposition: form-data; name="foo"; filename="foo"

bar
--bb3f05a247b43eede27a124ef8b968c5--
>>> files = {'foo': (None, 'bar')}
>>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))
--d5ca8c90a869c5ae31f70fa3ddb23c76
Content-Disposition: form-data; name="foo"

bar
--d5ca8c90a869c5ae31f70fa3ddb23c76--

文件也可以是双值元组的列表,如果你需要排序和/或多个相同名称的字段:

requests.post(
    'http://requestb.in/xucj9exu',
    files=(
        ('foo', (None, 'bar')),
        ('foo', (None, 'baz')),
        ('spam', (None, 'eggs')),
    )
)

如果同时指定了文件和数据,那么将使用什么来创建POST体取决于数据的值。如果data是字符串,则只使用它;否则,将同时使用数据和文件,首先列出数据中的元素。

还有一个优秀的请求-工具带项目,它包括高级的多部件支持。它接受与files形参相同格式的字段定义,但与请求不同,它默认不设置filename形参。此外,它可以从打开的文件对象中传输请求,其中请求将首先在内存中构造请求体:

from requests_toolbelt.multipart.encoder import MultipartEncoder

mp_encoder = MultipartEncoder(
    fields={
        'foo': 'bar',
        # plain file object, no filename or mime type produces a
        # Content-Disposition header with just the part name
        'spam': ('spam.txt', open('spam.txt', 'rb'), 'text/plain'),
    }
)
r = requests.post(
    'http://httpbin.org/post',
    data=mp_encoder,  # The MultipartEncoder is posted as data, don't use files=...!
    # The MultipartEncoder provides the content-type header with the boundary:
    headers={'Content-Type': mp_encoder.content_type}
)

字段遵循相同的约定;使用2到4个元素的元组来添加文件名、mime类型的部分或额外的头文件。与files形参不同,如果不使用元组,则不会尝试查找默认的文件名值。

自从编写了以前的一些答案之后,请求已经发生了变化。在Github上看看这个问题的更多细节,这条评论是一个例子。

简而言之,files参数接受一个字典,键为表单字段的名称,值为字符串或2、3或4长度的元组,如请求快速入门中的POST一个多部分编码文件部分所述:

>>> url = 'http://httpbin.org/post'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}

在上面,元组的组成如下:

(filename, data, content_type, headers)

如果值只是一个字符串,文件名将与键相同,如下所示:

>>> files = {'obvius_session_id': '72c2b6f406cdabd578c5fd7598557c52'}

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

72c2b6f406cdabd578c5fd7598557c52

如果值是一个元组,并且第一个条目是None,则filename属性将不包括在内:

>>> files = {'obvius_session_id': (None, '72c2b6f406cdabd578c5fd7598557c52')}

Content-Disposition: form-data; name="obvius_session_id"
Content-Type: application/octet-stream

72c2b6f406cdabd578c5fd7598557c52

下面是使用请求上传带有附加参数的单个文件的简单代码片段:

url = 'https://<file_upload_url>'
fp = '/Users/jainik/Desktop/data.csv'

files = {'file': open(fp, 'rb')}
payload = {'file_id': '1234'}

response = requests.put(url, files=files, data=payload, verify=False)

请注意,您不需要显式地指定任何内容类型。

注:想评论上述答案之一,但不能因为低声誉,所以起草了一个新的回应在这里。

您需要使用网站HTML中上传文件的name属性。例子:

autocomplete="off" name="image">

你看到name="image">?你可以在上传文件的网站的HTML中找到它。您需要使用它来上传Multipart/form-data文件

脚本:

import requests

site = 'https://prnt.sc/upload.php' # the site where you upload the file
filename = 'image.jpg'  # name example

这里,在image的位置,用HTML添加上传文件的名称

up = {'image':(filename, open(filename, 'rb'), "multipart/form-data")}

如果上传需要点击按钮进行上传,可以这样使用:

data = {
     "Button" : "Submit",
}

然后启动请求

request = requests.post(site, files=up, data=data)

完成,文件上传成功

import requests
# assume sending two files
url = "put ur url here"
f1 = open("file 1 path", 'rb')
f2 = open("file 2 path", 'rb')
response = requests.post(url,files={"file1 name": f1, "file2 name":f2})
print(response)