Вопрос-Ответ

How to upload file with python requests?

Как загрузить файл с запросами python?

Я выполняю простую задачу по загрузке файла с помощью библиотеки запросов Python. Я искал в Stack Overflow, и, похоже, ни у кого не возникло такой же проблемы, а именно, что файл не получен сервером:

import requests
url='http://nesssi.cacr.caltech.edu/cgi-bin/getmulticonedb_release2.cgi/post'
files={'files': open('file.txt','rb')}
values={'upload_file' : 'file.txt' , 'DB':'photcat' , 'OUT':'csv' , 'SHORT':'short'}
r=requests.post(url,files=files,data=values)

Я заполняю значение ключевого слова 'upload_file' своим именем файла, потому что, если я оставлю его пустым, там будет написано

Error - You must select a file to upload!

И теперь я получаю

File  file.txt  of size    bytes is  uploaded successfully!
Query service results: There were 0 lines.

Который появляется, только если файл пуст. Итак, я застрял в вопросе, как успешно отправить мой файл. Я знаю, что файл работает, потому что, если я зайду на этот веб-сайт и вручную заполню форму, он вернет хороший список подходящих объектов, что мне и нужно. Я был бы очень признателен за все подсказки.

Некоторые другие связанные темы (но не отвечающие на мою проблему):

Переведено автоматически
Ответ 1

Если upload_file подразумевается как файл, используйте:

files = {'upload_file': open('file.txt','rb')}
values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'}

r = requests.post(url, files=files, data=values)

и requests отправит текст сообщения формы, состоящий из нескольких частей, с upload_file полем, заданным для содержимого file.txt файла.

Имя файла будет включено в заголовок mime для определенного поля:

>>> import requests
>>> open('file.txt', 'wb') # create an empty demo file
<_io.BufferedWriter name='file.txt'>
>>> files = {'upload_file': open('file.txt', 'rb')}
>>> print(requests.Request('POST', 'http://example.com', files=files).prepare().body.decode('ascii'))
--c226ce13d09842658ffbd31e0563c6bd
Content-Disposition: form-data; name="upload_file"; filename="file.txt"


--c226ce13d09842658ffbd31e0563c6bd--

Обратите внимание на параметр filename="file.txt".

Вы можете использовать кортеж для files значения сопоставления, содержащий от 2 до 4 элементов, если вам нужно больше контроля. Первым элементом является имя файла, за которым следует содержимое, а также необязательное значение заголовка content-type и необязательное сопоставление дополнительных заголовков:

files = {'upload_file': ('foobar.txt', open('file.txt','rb'), 'text/x-spam')}

Это устанавливает альтернативное имя файла и тип содержимого, исключая необязательные заголовки.

Если вы хотите, чтобы все тело записи было взято из файла (без указания других полей), то не используйте files параметр, просто опубликуйте файл непосредственно как data. Затем вы, возможно, захотите также задать Content-Type заголовок, поскольку в противном случае ничего не будет установлено. Смотрите Запросы Python - ОТПРАВКА данных из файла.

Ответ 2

(2018) новая библиотека запросов python упростила этот процесс, мы можем использовать переменную 'files', чтобы сигнализировать, что мы хотим загрузить файл с кодировкой из нескольких частей

url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}

r = requests.post(url, files=files)
r.text
Ответ 3

Загрузка клиентом

Если вы хотите загрузить один файл с помощью requests библиотеки Python, то requests lib поддерживает потоковые загрузки, которые позволяют вам отправлять большие файлы или потоки без чтения в память.

with open('massive-body', 'rb') as f:
requests.post('http://some.url/streamed', data=f)

Серверная часть

Затем сохраните файл на server.py стороне таким образом, чтобы сохранить поток в файл без загрузки в память. Ниже приведен пример использования загрузки файлов Flask.

@app.route("/upload", methods=['POST'])
def upload_file():
from werkzeug.datastructures import FileStorage
FileStorage(request.stream).save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return 'OK', 200

Или используйте синтаксический анализ данных формы werkzeug, как указано в исправлении проблемы "загрузка больших файлов съедает память", чтобы избежать неэффективного использования памяти при загрузке больших файлов (файл размером около 22 Гигабайт за ~ 60 секунд. Использование памяти постоянно составляет около 13 Мбайт.).

@app.route("/upload", methods=['POST'])
def upload_file():
def custom_stream_factory(total_content_length, filename, content_type, content_length=None):
import tempfile
tmpfile = tempfile.NamedTemporaryFile('wb+', prefix='flaskapp', suffix='.nc')
app.logger.info("start receiving file ... filename => " + str(tmpfile.name))
return tmpfile

import werkzeug, flask
stream, form, files = werkzeug.formparser.parse_form_data(flask.request.environ, stream_factory=custom_stream_factory)
for fil in files.values():
app.logger.info(" ".join(["saved form name", fil.name, "submitted as", fil.filename, "to temporary file", fil.stream.name]))
# Do whatever with stored file at `fil.stream.name`
return 'OK', 200
Ответ 4

Вы можете отправить любой файл через post api при вызове API, просто нужно упомянуть files={'any_key': fobj}

import requests
import json

url = "https://request-url.com"

headers = {"Content-Type": "application/json; charset=utf-8"}

with open(filepath, 'rb') as fobj:
response = requests.post(url, headers=headers, files={'file': fobj})

print("Status Code", response.status_code)
print("JSON Response ", response.json())
2023-07-09 19:33 python file python-requests