如何用Python通过multipart/form-data POST发送内存字节文件?
问题:直接转发图片字节到VK上传API(无需落地存储)
当前实现是通过requests.get('https://service.com/test.jpeg')获取图片字节后,先写入本地硬盘,再调用以下代码发送:
def send_file(path_to_image: str): url = get_upload_link() data = {'photo': open(path_to_image, 'rb')} r = requests.post(url, files=data) send_file("test.jpeg")
希望直接使用bytes对象完成转发,无需落地存储,但多次尝试均失败:
- 尝试1:直接传递
bytes给open(),触发报错ValueError: embedded null byte
def send_file(image: bytes): url = get_upload_link() data = {'photo': open(image, 'rb')} r = requests.post(url, files=data)
- 尝试2:用
BytesIO包装bytes,但后端返回与传入files=None相同的响应
def upload_photo(image: bytes): url = get_upload_link() file = BytesIO(image) data = {'photo': file} r = requests.post(url, files=data)
此外还尝试过file.getbuffer()、file.read()返回值、StringIO对象等方式,均未解决问题。
解决方案
VK上传API需要明确的文件元信息(文件名、MIME类型)才能正确处理上传请求,只需给files中的文件对象补充这些信息即可,无需构造_io.BufferedReader。修改后的代码如下:
from io import BytesIO import requests def upload_photo(image: bytes): url = get_upload_link() # 用BytesIO包装图片字节,同时指定文件名和图片MIME类型 file_buffer = BytesIO(image) files = { 'photo': ('test.jpeg', file_buffer, 'image/jpeg') } response = requests.post(url, files=files) return response
关键说明
- 尝试1错误原因:
open()函数仅接受文件路径字符串,不能直接传入bytes对象,因此触发参数类型错误。 - 尝试2错误原因:仅传递
BytesIO对象时,requests不会自动生成文件名和Content-Type请求头,VK API无法识别这是有效图片文件,因此返回无文件上传的响应。 - 补充元信息后,请求格式会和本地文件上传完全一致,API就能正常处理。
内容的提问来源于stack exchange,提问作者Neykuratick
相关产品推荐
相关产品推荐

