Загрузка больших zip-файлов на веб-сайт с использованием Python

#python #python-2.7

#python #python-2.7

Вопрос:

У меня следующая проблема: мне нужно загрузить большие zip-файлы (обычно > 500 МБ, максимум около 5 ГБ) на веб-сайт, который затем обрабатывает эти файлы. Я делаю это в Python 2.7.16 32-разрядной версии Windows. К сожалению, я не могу изменить свою настройку (с 32-разрядной на 64-разрядную) и не могу установить дополнительные плагины Python (у меня есть запросы, urllib и urllib2 и несколько других установленных) из-за ограничений компании. Теперь мой код выглядит так:

  import requests

 FileList=["C:File01.zip", "C:FileA02.zip", "C:UserFile993.zip"]
 UploadURL = "https://mywebsite.com/submitFile"
 for FilePath in FileList:
    print("Upload file: " str(FilePath))
    session = requests.Session()
        with open(FilePath, "rb") as file:
        session.post(UploadURL,data={'file':'Send file'},files={'FileToBeUploaded':FilePath})
    print("Upload done: " str(FilePath))
    session.close()
  

Поскольку мой FileList довольно длинный (> 100 записей), я просто вставил сюда его отрывок. Приведенный выше код хорошо работает, если размер файла меньше 600 МБ. Любой файл выше, который выдаст мне эту ошибку:

   File "<stdin>", line 1, in <module>
  File "C:UsersAAA253DesktopDingDong.py", line 39, in <module>
    session.post(UploadURL,data={'file':'Send file'},files={'FileToBeUploaded':FilePath})
  File "C:Python27libsite-packagesrequestssessions.py", line 522, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "C:Python27libsite-packagesrequestssessions.py", line 461, in request
    prep = self.prepare_request(req)
  File "C:Python27libsite-packagesrequestssessions.py", line 394, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "C:Python27libsite-packagesrequestsmodels.py", line 297, in prepare
    self.prepare_body(data, files, json)
  File "C:Python27libsite-packagesrequestsmodels.py", line 455, in prepare_body
    (body, content_type) = self._encode_files(files, data)
  File "C:Python27libsite-packagesrequestsmodels.py", line 158, in _encode_files
    body, content_type = encode_multipart_formdata(new_fields)
  File "C:Python27libsite-packagesrequestspackagesurllib3filepost.py", line 86, in encode_multipart_formdata
    body.write(data)
MemoryError
  

Я уже проверил форум здесь, чтобы найти некоторые решения, но, к сожалению, я не смог найти ни одного подходящего решения. У кого-нибудь есть идея о том, как это сделать? Может ли это быть сделано путем загрузки файла по частям? Если да, то как загрузить файл по частям, чтобы сервер не «отменял» операцию?

Редактировать: используя ответ от @AKX, я использую этот код:

 import requests
from requests_toolbelt.multipart import encoder

FileList=["C:File01.zip", "C:FileA02.zip", "C:UserFile993.zip"]
UploadURL = "https://mywebsite.com/submitFile"
for FilePath in FileList:
    session = requests.Session()
    with open(FilePath, 'rb') as f:
        form = encoder.MultipartEncoder({"documents": (FilePath, f, "application/octet-stream"),"composite": "NONE",})
        headers = {"Prefer": "respond-async", "Content-Type": form.content_type}
        resp = session.post(UploadURL,data={'file':'Send file'},files={'FileToBeUploaded':form})
    session.close()
  

Тем не менее я получаю почти те же ошибки:

     File "<stdin>", line 1, in <module>
  File "C:UsersAAA253DesktopDingDong.py", line 48, in <module>
    resp =  session.post(UploadURL,data={'file':'Send file'},files={'FileToBeUploaded':form})
  File "C:Python27libsite-packagesrequests-2.24.0-py2.7.eggrequestssessions.py", line 578, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "C:Python27libsite-packagesrequests-2.24.0-py2.7.eggrequestssessions.py", line 516, in request
    prep = self.prepare_request(req)
  File "C:Python27libsite-packagesrequests-2.24.0-py2.7.eggrequestssessions.py", line 459, in prepare_request
    hooks=merge_hooks(request.hooks, self.hooks),
  File "C:Python27libsite-packagesrequests-2.24.0-py2.7.eggrequestsmodels.py", line 317, in prepare
    self.prepare_body(data, files, json)
  File "C:Python27libsite-packagesrequests-2.24.0-py2.7.eggrequestsmodels.py", line 505, in prepare_body
    (body, content_type) = self._encode_files(files, data)
  File "C:Python27libsite-packagesrequests-2.24.0-py2.7.eggrequestsmodels.py", line 159, in _encode_files
    fdata = fp.read()
  File "buildbdist.win32eggrequests_toolbeltmultipartencoder.py", line 314, in read
  File "buildbdist.win32eggrequests_toolbeltmultipartencoder.py", line 194, in _load
  File "buildbdist.win32eggrequests_toolbeltmultipartencoder.py", line 256, in _write
  File "buildbdist.win32eggrequests_toolbeltmultipartencoder.py", line 552, in append
MemoryError
  

Комментарии:

1. вы проверили, принимает ли ваш целевой сайт chunked?

Ответ №1:

Скорее всего, вам не понадобится requests-toolbelt многопартенкодер потоковой передачи.

Даже если ограничения вашей компании запрещают установку новых пакетов, вы, скорее всего, можете добавить нужные вам части requests_toolbelt (возможно, весь пакет) в каталог вашего проекта.

Комментарии:

1. Я реализовал это сейчас и расширил свой первый пост. Я все еще получаю ошибки.

2. Вам нужно использовать data=form , а не files={...: form} .

3. Хорошо, используя вашу идею, я все еще не добился этого. Я не вижу взаимодействия между кодом и моим веб-сайтом. На моем веб-сайте у меня есть 2 кнопки для отправки файла. Кнопка под названием «Отправить файл» запускает загрузку, в то время как на второй кнопке под названием «FileToBeUploaded» вам нужно выбрать файл, который вы хотите загрузить. Я делаю это совершенно неправильно, используя MultipartEncoder: m = MultipartEncoder(fields={'file':'Send file', 'FileToBeUploaded': ('filename', open(FilePath, 'rb'), '.zip')}) r = session.post(UploadURL, data=m, headers={'Content-Type': m.content_type})

4. Но вы не получаете ошибку памяти с этой версией, верно? Затем нужно отправить правильные данные.

5. Ошибка памяти исчезла, но сервер не отвечает, поэтому я боюсь, что я не получаю сообщение об ошибке, но вместо этого отправка не активна (и поэтому также загрузка в память).