你好呀,
当我尝试使用以下代码通过 python 请求和 Zenodo API(沙箱)上传大于 100 MB 的测试文件时
data = {'filename': 'test.zip'}
files = {'file': open(filename, 'rb')}
r = requests.post("https://sandbox.zenodo.org/api/deposit/depositions/%s/files?access_token=TOKEN" % deposition_id, data=data, files=files)
它返回 http 错误代码413
(“413 请求实体太大”,顺便说一句,zenodo API 文档中没有记录)。
对小于 100 MB 的文件进行测试的相同代码有效并返回201
。
我是否已达到文件大小限制? (如果是这样,最好将其添加到文档中)。 或者这可能是由于“请求”包 - 我是否必须将数据分成多个部分?
您必须使用我们新的文件上传 API(我们尚未发布)来上传大于 100MB 的文件。 这是因为当前的 API 使用application/mulitpart-formdata
来上传文件,效率不高。 在新的 API 中,您可以在 PUT 请求中流式传输文件的二进制内容,该请求要快得多,并且两端都不需要任何编码/解码。 今天稍后我会给你一个例子。
感谢您调查此事! 我对新 API 的示例感到很兴奋。
也许你想考虑 python 包“requests-toolbelt”,它也允许流式传输多部分表单数据对象。 但我想任何没有编码要求的解决方案都值得赞赏。
抱歉这么久才回复这个问题:
1) 找到您的存储桶 URL:
$ curl -H "Accept: application/json" -H "Authorization: Bearer <access token>" "https://www.zenodo.org/api/deposit/depositions/<deposit id>"
{
"links": {
"bucket": "https://www.zenodo.org/api/files/<bucket id>",
...
},
...
2) 上传文件到bucket
$ curl -X PUT -H "Accept: application/json" -H "Content-Type: application/octet-stream" -H "Authorization: Bearer <access_token>" -d @<path to local file> https://www.zenodo.org/api/files/<bucket id>/<filename>
请注意,存储桶是版本化的,因此为了再次完全删除文件,您必须使用版本链接。 从列出存储桶中找到它:
$ curl -H "Accept: application/json" -H "Authorization: Bearer <access token>" "https://www.zenodo.org/api/files/<bucket id>”
{
"contents": [
{
"links": {
"version": "https://zenodo.org/api/files/<bucket id>/<filename>?versionId=<versionId>",
...
},
"key": "<filename>",
...
},
...
删除文件:
$ curl -X DELETE -H "Accept: application/json" -H "Authorization: Bearer <access_token>" https://www.zenodo.org/api/files/<bucket id>/<filename>?versionId=<versionId>”
以防万一有人遇到这个问题,这里有一些 Python 可以使用新的 API 来完成文件上传部分。 这相当于上面概述的用于上传单个文件的 CURL 调用。 我已经用 160MB 的文件对其进行了测试,但该文件的 API失败了。 这也使用请求(文档化 API 使用的)并简单地进行新提交并上传文件。 请注意,使用的 URL 是沙盒 URL。
import requests
r = requests.post('https://sandbox.zenodo.org/api/deposit/depositions',
params={'access_token': ACCESS_TOKEN}, json={},
headers={"Content-Type": "application/json"})
print r.status_code
bucket_url = r.json()['links']['bucket']
filename='bigfile.txt'
r = requests.put('%s/%s' % (bucket_url,filename),
data=open(filename, 'rb'),
headers={"Accept":"application/json",
"Authorization":"Bearer %s" % ACCESS_TOKEN,
"Content-Type":"application/octet-stream"})
print r.status_code
@lnielsen @jakelever
您认为可以使用requests.put
将分块文件流式传输到存储桶中吗?
语境:
我有一组大文件,我想对其进行压缩,而无需事先在内存或磁盘上创建 zipfile。 我想将生成器对象传递给请求方法的八位字节流。
在尝试使用 API 上传文件时偶然发现了这一点。 对我来说,流 API 失败了,因为只有大约 986 Kb 文件的一半被上传,导致 PDF 损坏。 基于http://killtheradio.net/tricks-hacks/curl-cli-not-sending-full-file-data-when-using-data-binary/然后我用-T <path to file>
替换了-d @<path to file>
-T <path to file>
在 curl 命令行和整个文件上传。
最有用的评论
以防万一有人遇到这个问题,这里有一些 Python 可以使用新的 API 来完成文件上传部分。 这相当于上面概述的用于上传单个文件的 CURL 调用。 我已经用 160MB 的文件对其进行了测试,但该文件的 API失败了。 这也使用请求(文档化 API 使用的)并简单地进行新提交并上传文件。 请注意,使用的 URL 是沙盒 URL。