Python请求:在单个请求中发布JSON和文件

relj7zay  于 2022-11-19  发布在  Python
关注(0)|答案(7)|浏览(147)

我 需要 执行 一 个 API 调用 来 上传 一 个 文件 以及 一 个 包含 文件 详细 信息 的 JSON 字符 串 。
我 尝试 使用 python requests lib 来 实现 这 一 点 :

import requests

info = {
    'var1' : 'this',
    'var2'  : 'that',
}

data = json.dumps({
    'token' : auth_token,
    'info'  : info,
})

headers = {'Content-type': 'multipart/form-data'}

files = {'document': open('file_name.pdf', 'rb')}

r = requests.post(url, files=files, data=data, headers=headers)

中 的 每 一 个
这 会 掷 回 下列 错误 :

raise ValueError("Data must not be a string.")
 ValueError: Data must not be a string

格式
如果 我 从 请求 中 删除 " 文件 " , 它 就 可以 工作 。
如果 我 从 请求 中 删除 " 数据 " , 它 就 可以 工作 。
如果 我 不 将 数据 编码 为 JSON , 它 就 可以 工作 。
由于 这个 原因 , 我 认为 这个 错误 与 在 同一 个 请求 中 发送 JSON 数据 和 文件 有关 。
有 什么 办法 让 它 工作 吗 ?

aemubtdh

aemubtdh1#

如何将JSON作为多部分POST请求的一部分发送

请勿自行设定Content-type信头,让pyrequests产生

def send_request():
    payload = {"param_1": "value_1", "param_2": "value_2"}
    files = {
        'json': (None, json.dumps(payload), 'application/json'),
        'file': (os.path.basename(file), open(file, 'rb'), 'application/octet-stream')
    }

    r = requests.post(url, files=files)
    print(r.content)
qltillow

qltillow2#

不要使用json编码。

import requests

info = {
    'var1' : 'this',
    'var2'  : 'that',
}

data = {
    'token' : auth_token,
    'info'  : info,
}

headers = {'Content-type': 'multipart/form-data'}

files = {'document': open('file_name.pdf', 'rb')}

r = requests.post(url, files=files, data=data, headers=headers)

请注意,这不一定是您想要的,因为它将成为另一个表单数据节。

wqsoz72f

wqsoz72f3#

我不认为你可以在一个多部分编码的文件中同时发送数据和文件,所以你需要把你的数据也变成一个“文件”:

files = {
    'data' : data,
    'document': open('file_name.pdf', 'rb')
}

r = requests.post(url, files=files, headers=headers)
pes8fvy9

pes8fvy94#

我 一直 在 使用 requests==2.22.0
对 我 来说 , 下面 的 代码 工作 .

import requests

data = {
    'var1': 'this',
    'var2': 'that'
}

r = requests.post("http://api.example.com/v1/api/some/",
    files={'document': open('doocument.pdf', 'rb')},
    data=data,
    headers={"Authorization": "Token jfhgfgsdadhfghfgvgjhN"}. #since I had to authenticate for the same
)

print (r.json())

中 的 每 一 个

ctzwtxfj

ctzwtxfj5#

为了发送Facebook Messenger API,我将所有的有效载荷字典值都改为字符串,然后,我可以将有效载荷作为data参数传递。

import requests

ACCESS_TOKEN = ''

url = 'https://graph.facebook.com/v2.6/me/messages'
payload = {
        'access_token' : ACCESS_TOKEN,
        'messaging_type' : "UPDATE",
        'recipient' : '{"id":"1111111111111"}',
        'message' : '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}',
}
files = {'filedata': (file, open(file, 'rb'), 'image/png')}
r = requests.post(url, files=files, data=payload)
3ks5zfa0

3ks5zfa06#

1.发送请求

import json
import requests

cover   = 'superneat.jpg'
payload = {'title': 'The 100 (2014)', 'episodes': json.dumps(_episodes)}
files   = [
            ('json', ('payload.json', json.dumps(payload), 'application/json')),
            ('cover', (cover, open(cover, 'rb')))
          ]
r       = requests.post("https://superneatech.com/store/series", files=files)

print(r.text)

2.接收请求

  • 您将以文件形式接收JSON数据,获取内容并继续...*
    **参考:**查看此处
gg58donl

gg58donl7#

更重要的是:

files = {
    'document': open('file_name.pdf', 'rb')
}

只有当您的文件与脚本位于同一目录下时,此方法才有效。
如果要从不同的目录附加文件,您应该执行以下操作:

files = {
    'document': open(os.path.join(dir_path, 'file_name.pdf'), 'rb')
}

其中,dir_path是包含**'file_name.pdf'文件的目录。
但是,如果您想发送多个PDF,该怎么办?
你可以简单地创建一个自定义函数来返回你需要的文件列表(在你的例子中,只能是那些扩展名为
.pdf**的文件)。这也包括子目录中的文件(递归搜索文件):

def prepare_pdfs():
    return sorted([os.path.join(root, filename) for root, dirnames, filenames in os.walk(dir_path) for filename in filenames if filename.endswith('.pdf')])

那你就叫它:

my_data = prepare_pdfs()

并以简单循环:

for file in my_data:

    pdf = open(file, 'rb')

    files = {
        'document': pdf
    }

    r = requests.post(url, files=files, ...)

相关问题