python请求文件上传

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22567306/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:11:03  来源:igfitidea点击:

python requests file upload

pythonfilefile-uploadpython-requests

提问by scichris

I'm performing a simple task of uploading a file using Python requests library. I searched Stack Overflow and no one seemed to have the same problem, namely, that the file is not received by the server:

我正在执行使用 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)

I'm filling the value of 'upload_file' keyword with my filename, because if I leave it blank, it says

我正在用我的文件名填充 'upload_file' 关键字的值,因为如果我将其留空,它会说

Error - You must select a file to upload!

And now I get

现在我得到

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

Which comes up only if the file is empty. So I'm stuck as to how to send my file successfully. I know that the file works because if I go to this website and manually fill in the form it returns a nice list of matched objects, which is what I'm after. I'd really appreciate all hints.

仅当文件为空时才会出现。所以我不知道如何成功发送我的文件。我知道该文件有效,因为如果我访问该网站并手动填写表格,它会返回一个很好的匹配对象列表,这正是我所追求的。我真的很感激所有的提示。

Some other threads related (but not answering my problem):

其他一些相关的线程(但没有回答我的问题):

采纳答案by Martijn Pieters

If upload_fileis meant to be the file, use:

如果upload_file是文件,请使用:

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

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

and requestswill send a multi-part form POST body with the upload_filefield set to the contents of the file.txtfile.

并且requests将派遣一个多部分表单POST体与upload_file字段设置为内容file.txt的文件。

The filename will be included in the mime header for the specific field:

文件名将包含在特定字段的 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--

Note the filename="file.txt"parameter.

注意filename="file.txt"参数。

You can use a tuple for the filesmapping value, with between 2 and 4 elements, if you need more control. The first element is the filename, followed by the contents, and an optional content-type header value and an optional mapping of additional headers:

files如果您需要更多控制,您可以使用元组作为映射值,包含 2 到 4 个元素。第一个元素是文件名,然后是内容,以及可选的 content-type 标头值和附加标头的可选映射:

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

This sets an alternative filename and content type, leaving out the optional headers.

这将设置替代文件名和内容类型,省略可选标题。

If you are meaning the whole POST bodyto be taken from a file (with no other fields specified), then don't use the filesparameter, just post the file directly as data. You then may want to set a Content-Typeheader too, as none will be set otherwise. See Python requests - POST data from a file.

如果您的意思是从文件中获取整个 POST 正文(没有指定其他字段),则不要使用该files参数,只需将文件直接作为data. 然后您可能还想设置一个Content-Type标题,否则将不会设置任何标题。请参阅Python 请求 - 来自文件的 POST 数据

回答by laycat

(2018) the new python requests library has simplified this process, we can use the 'files' variable to signal that we want to upload a multipart-encoded file

(2018) 新的 python requests 库简化了这个过程,我们可以使用 'files' 变量来表示我们想要上传一个多部分编码的文件

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

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

回答by gihanchanuka

Client Upload

客户端上传

If you want to upload a single file with Python requestslibrary, then requests lib supports streaming uploads, which allow you to send large filesor streams without reading into memory.

如果您想使用 Pythonrequests库上传单个文件,则 requests lib支持流式上传,它允许您发送大文件或流而无需读入内存

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

Server Side

服务器端

Then store the file on the server.pyside such that save the stream into file without loading into the memory. Following is an example with using Flask file uploads.

然后将文件存储在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

Or use werkzeug Form Data Parsingas mentioned in a fix for the issue of "large file uploads eating up memory" in order to avoid using memory inefficiently on large files upload(s.t. 22 GiB file in ~60 seconds. Memory usage is constant at about 13 MiB.).

或者使用werkzeug 表单数据解析,如修复“大文件上传占用内存”问题中提到的那样,以避免在大文件上传时低效使用内存(st 22 GiB 文件在 ~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

回答by Harshit Trivedi

In Ubuntu you can apply this way,

在 Ubuntu 中你可以这样应用,

to save file at some location (temporary) and then open and send it to API

将文件保存在某个位置(临时),然后打开并将其发送到 API

      path = default_storage.save('static/tmp/' + f1.name, ContentFile(f1.read()))
      path12 = os.path.join(os.getcwd(), "static/tmp/" + f1.name)
      data={} #can be anything u want to pass along with File
      file1 = open(path12, 'rb')
      header = {"Content-Disposition": "attachment; filename=" + f1.name, "Authorization": "JWT " + token}
       res= requests.post(url,data,header)