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


当前回答

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

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)

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

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

其他回答

自从编写了以前的一些答案之后,请求已经发生了变化。在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

为了澄清上面的例子,

即使不需要上传任何文件,也需要使用files参数发送多部分表单POST请求。

文件= {}

不幸的是,这行不通。

您将需要放入一些虚拟值,例如。

files={"foo": "bar"}

当我试图上传文件到Bitbucket的REST API时,我遇到了这个问题,不得不写这个讨厌的东西,以避免可怕的“不支持的媒体类型”错误:

url = "https://my-bitbucket.com/rest/api/latest/projects/FOO/repos/bar/browse/foobar.txt"
payload = {'branch': 'master', 
           'content': 'text that will appear in my file',
           'message': 'uploading directly from python'}
files = {"foo": "bar"}
response = requests.put(url, data=payload, files=files)

:O=

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

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)

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

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

这是在多部分请求中发送文件的一种方法

import requests
headers = {"Authorization": "Bearer <token>"}
myfile = 'file.txt'
myfile2 = {'file': (myfile, open(myfile, 'rb'),'application/octet-stream')}
url = 'https://example.com/path'
r = requests.post(url, files=myfile2, headers=headers,verify=False)
print(r.content)

其他方法

import requests

url = "https://example.com/path"

payload={}
files=[
  ('file',('file',open('/path/to/file','rb'),'application/octet-stream'))
]
headers = {
  'Authorization': 'Bearer <token>'
}

response = requests.request("POST", url, headers=headers, data=payload, files=files)

print(response.text)

我都测试过了,两者都很好。

import json
import os
import requests
from requests_toolbelt import MultipartEncoder

AUTH_API_ENDPOINT = "http://localhost:3095/api/auth/login"

def file_upload(path_img, token ):
    url = 'http://localhost:3095/api/shopping/product/image'
    name_img = os.path.basename(path_img)

    mp_encoder = MultipartEncoder(
        fields={
            'email': 'mcm9@gmail.com',
            'source': 'tmall',
            'productId': 'product_0001',
            'image': (name_img, open(path_img, 'rb'), 'multipart/form-data')
        #'spam': ('spam.txt', open('spam.txt', 'rb'), 'text/plain'),
        }
    )

    head = {'Authorization': 'Bearer  {}'.format(token),
            'Content-Type': mp_encoder.content_type}

    with requests.Session() as s:
        result = s.post(url, data=mp_encoder, headers=head)

    return result

def do_auth(username, password, url=AUTH_API_ENDPOINT):
    data = {
        "email": username,
        "password": password
    }

    # sending post request and saving response as response object
    r = requests.post(url=url, data=data)

    # extracting response text
    response_text = r.text

    d = json.loads(response_text)
    # print(d)

    return d


if __name__ == '__main__':
    result = do_auth('mcm4@gmail.com','123456')
    token = result.get('data').get('payload').get('token')
    print(token)
    result = file_upload('/home/mcm/Pictures/1234.png',token)
    print(result.json())