简体   繁体   English

使用json发送分段上传

[英]send multipart upload with json

I'm trying to upload a video file along with some JSON using a REST API with requests in Python. 我正在尝试使用REST API和Python中的请求上传视频文件以及一些JSON。

Here is the example cURL for the request. 这是请求的示例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' }"

And here is my code. 这是我的代码。

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)

When I run this, the API server returns a MissingOrInvalidFileName error. 当我运行此命令时,API服务器返回MissingOrInvalidFileName错误。 If I leave out my data parameter, the file uploads correctly. 如果我遗漏了data参数,则文件将正确上传。 What is the correct way to make this request? 发出此请求的正确方法是什么?

Your file parameter is called filename in the curl request, and the metadata part should be a string (encoded to JSON); 您的文件参数在curl请求中称为filenamemetadata部分应为字符串(编码为JSON); it is one field and has a nested metadata object. 它是一个字段,并且具有嵌套的 metadata对象。 wordspaceId and folderId are keys in the outermost metadata object, not separate parameters: 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)

Finally solved! 终于解决了! Turns out requests encodes its multipart with data then files while the API required files then data. 最终,请求使用数据然后是文件对它的多部分进行编码,而API则需要先对数据进行编码。

@Martijn Pieters's solution of inputting all of the data as tuples almost works. @Martijn Pieters将所有数据输入为元组的解决方案几乎可以正常工作。 The only problem is setting the data this way breaks requests' ability to set the content-type header automatically (it thinks my data is content-type application/json). 唯一的问题是以这种方式设置数据会破坏请求自动设置content-type标头的能力(它认为我的数据是content-type application / json)。

In the end, I used request-toolbelt 's MultipartEncoder which allows me to order my multipart body using tuples and saves the content-type in its instance. 最后,我使用了request-toolbelt的MultipartEncoder,它使我可以使用元组对多部分主体进行排序,并将content-type保存在其实例中。 Here is the final working code. 这是最终的工作代码。

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})

Finally works. 终于可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM