发送带有JSON的多部分上传

0 投票
2 回答
2473 浏览
提问于 2025-04-18 14:10

我正在尝试使用Python中的requests库,通过REST API上传一个视频文件和一些JSON数据。

下面是这个请求的cURL示例。

curl -XPOST -i "https://io.cimediacloud.com/upload" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-F filename=@Movie.mov
-F metadata="{ 'metadata' : { 'Resolution' : '1080p', 'Language' : 'English' },        
'workspaceId' : 'a585b641a60843498543597d16ba0108', 'folderId' : 
'a585b641a60843498543597d16ba0108' }"

这是我的代码。

url = 'https://io.cimediacloud.com/upload'
files = {'file': ('video.mp4', open('files/video.mp4', 'rb')),
                  }
data = {'metadata': {'Resolution' : '1080p', 'Language' : 'English'},
        'workspaceId': your_workspace_id,
        'folderId': folder_id,}

r = session.post(url, files=files, data=data)

当我运行这个代码时,API服务器返回一个“缺少或无效的文件名”的错误。如果我不传递我的数据参数,文件就能正确上传。那么,正确的请求方式是什么呢?

2 个回答

1

终于解决了!原来请求的方式是先处理数据再处理文件,而API要求的是先处理文件再处理数据。

@Martijn Pieters 提出的把所有数据作为元组输入的方法差不多可行。唯一的问题是这样设置数据会导致请求无法自动设置内容类型的头信息(它认为我的数据是内容类型为 application/json)。

最后,我使用了 request-toolbelt 的 MultipartEncoder,这样我可以用元组来排列我的多部分内容,并且它会在实例中保存内容类型。下面是最终可以正常工作的代码。

m = MultipartEncoder([('filename', ('video.mp4', open('files/video.mp4', 'rb'))), 
                      ('metadata', json.dumps(metadata))])

r = session.post(url, data=m, headers={'Content-Type': m.content_type})

终于可以用了。

2

在你的curl请求中,文件参数叫做 filename,而 metadata 部分应该是一个字符串(需要转换成JSON格式);它是 一个 字段,并且包含一个 嵌套的 metadata 对象。 wordspaceIdfolderId 是最外层 metadata 对象中的键,而不是单独的参数:

import json

files = {'filename': ('video.mp4', open('files/video.mp4', 'rb')),
metadata = {
    'metadata': {'Resolution': '1080p', 'Language': 'English'},
    'workspaceId': your_workspace_id,
    'folderId': folder_id
}
data = {'metadata': json.dumps(metadata)}
r = session.post(url, files=files, data=data)

撰写回答