Zenodo: Не удалось загрузить файл большего размера через API в песочницу

Созданный на 26 сент. 2016  ·  6Комментарии  ·  Источник: zenodo/zenodo

Привет,

когда я пытаюсь загрузить тестовый файл> 100 МБ через запросы python и Zenodo API (песочница), используя следующий код

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 Request Entity Too Large», который, кстати, не задокументирован в документации API zenodo).

Тот же код, протестированный с файлами <100 МБ, работает и возвращает 201 .

Я достиг предельного размера файла? (если так, было бы хорошо добавить это в документацию). А может это из-за пакета "запросы" - надо ли данные multipart ставить?

Enhancement

Самый полезный комментарий

На всякий случай, если кто-то столкнется с этим, вот несколько Python для загрузки файлов с использованием нового API. Это эквивалентно описанному выше вызову CURL для загрузки одного файла. Я проверил это с файлом размером 160 МБ, который не удался с документированным API . При этом также используются запросы (которые использует документированный API), просто создается новое представление и выгружается файл. Обратите внимание, что используется 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

Все 6 Комментарий

Вам нужно будет использовать наш новый API загрузки файлов (который мы еще не опубликовали), чтобы загружать файлы размером более 100 МБ. Это связано с тем, что текущий 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) Загрузите файл в ведро

$ 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 для загрузки одного файла. Я проверил это с файлом размером 160 МБ, который не удался с документированным API . При этом также используются запросы (которые использует документированный API), просто создается новое представление и выгружается файл. Обратите внимание, что используется 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 ?
Контекст:
У меня есть набор больших файлов, которые я хочу заархивировать без предварительного создания zip-файла в памяти или на диске. Я хотел бы передать объект-генератор в октетный поток метода запроса.

Наткнулся на это при попытке загрузить файлы с помощью API. Для меня потоковый API не удался, так как была загружена только половина файла размером 986 КБ, что привело к повреждению PDF-файла. На основе http://killtheradio.net/tricks-hacks/curl-cli-not-sending-full-file-data-when-using-data-binary/ я затем заменил -d @<path to file> на -T <path to file> в командной строке curl и весь файл загружен.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги