Подтвердить что ты не робот

Загрузка файлов python

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

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.

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

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

4b9b3361

Ответ 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 будут отправлять тело POST из нескольких upload_file полем 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 элементами, если вам нужно больше контроля. Первым элементом является имя файла, за которым следует содержимое, а также необязательное значение заголовка типа содержимого и необязательное сопоставление дополнительных заголовков:

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

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

Если вы имеете в виду все тело POST, которое нужно извлечь из файла (без указания других полей), не используйте параметр files, просто отправьте файл напрямую в виде data. Затем вы можете захотеть установить заголовок Content-Type, так как иначе не будет установлен ни один.

Ответ 2

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

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

r = requests.post(url, files=files)
r.text

Ответ 3

Клиент Uplaod

Если вы хотите загрузить один файл с библиотекой requests Python, то запросы 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, как упоминалось в исправлении для проблемы " загрузки больших файлов, израсходовавшей память ", чтобы избежать неэффективного использования памяти при загрузке больших файлов (файл st 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