Как загрузить большой файл, используя Python 3, используя только встроенные модули? - PullRequest
1 голос
/ 03 мая 2019

Я пытаюсь загрузить файл размером 32+ МБ на сервер с помощью API. Единственное ограничение, которое у меня есть, - это использование только встроенных модулей. Я видел много примеров использования библиотеки requests, но я пытаюсь решить с помощью urllib. Используя curl в качестве PoC, я сделал эту работу следующим образом:

curl -v --request POST --url 'https://domain/upload/long-string/' --form 'apikey=my-api-key' --form 'file=@my-file.extension'

Используя urllib, я написал код ниже, но он не работает, потому что сервер всегда возвращает ошибку 400:

import urllib

def post_bigfile(upload_url, file, auth, timeout):
        headers = {'Accept': '*/*', 'Content-Type': 'multipart/form-data'}
        data = {'file': file, 'apikey': auth}
        req = urllib.request.Request(upload_url, headers=headers, 
            data=urlencode(data).encode('utf-8'), method='POST')
        return urllib.request.urlopen(req, timeout=timeout)

post_bigfile('https://domain/upload/long-string/', open('my-file.extension','rb'), 'my-api-key', 20)

Я пытался использовать разные значения Content-Type и Accept, но это все равно не работает. Что я мог сделать не так? Есть ли другой встроенный модуль, который я мог бы использовать, чтобы лучше решить эту проблему?

1 Ответ

0 голосов
/ 03 мая 2019

Намек на то, что вы делаете неправильно, можно найти здесь:

'Content-Type': 'multipart/form-data'
headers=headers

Некоторое время назад я также был занят командами curl, которые отправляли многокомпонентные данные форм и пытались исследовать их только с помощью встроенных библиотек python (то есть, не запросов). После того, как вы положили --form в curl, вам даже не нужно указывать аргумент curl --headers "Content-Type: multipart/form-data", он просто по умолчанию принимает его. Может быть, вы не понимали, что это делает Керл.

Посмотрите на этот , python не поддерживает этот тип Mime. Проблема Python связана с https://bugs.python.org/issue3244, и я думаю, что вам лучше всего подойдет этот скрипт: https://pymotw.com/3/urllib.request/#uploading-files, если вы действительно хотите сделать это только со стандартными библиотеками.

Я предполагаю, что вы не управляете сервером, который получает этот файл, и похоже, что он требует multipart / form-data с двумя элементами "apikey" и "file". Если вы не можете изменить то, что хочет этот сервер, на что-то, что urllib может POST, вам придется использовать запросы или посмотреть, сможете ли вы заставить этот большой класс MultiPartForm работать.

...