python请求文件上传

python请求文件上传,python,file,file-upload,python-requests,Python,File,File Upload,Python Requests,我正在使用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':'phot

我正在使用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.
只有当文件为空时才会显示。所以我一直在思考如何成功地发送文件。我知道这个文件是有效的,因为如果我去这个网站手动填写表单,它会返回一个匹配对象的列表,这就是我想要的。我真的很感激所有的提示

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


如果
上传文件
是该文件,请使用:

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

r = requests.post(url, files=files, data=values)
请求
将发送一个多部分表单帖子正文,其中
上传文件
字段设置为
文件.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--
这将设置一个可选的文件名和内容类型,省去可选的标题

如果您想从一个文件(没有指定其他字段)中获取整个帖子正文,那么不要使用
files
参数,只需将该文件直接作为
数据发布即可。然后,您可能还需要设置
内容类型
标题,否则不会设置任何标题。请参阅。

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

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

r = requests.post(url, files=files)
r.text
客户端上载 如果要使用Python
请求库上载单个文件,请使用requests lib,这样就可以发送大文件或流,而无需读取内存

with open('massive-body', 'rb') as f:
    requests.post('http://some.url/streamed', data=f)
服务器端 然后将文件存储在
server.py
端,这样就可以将流保存到文件中,而无需加载到内存中。下面是一个使用的示例

或如“”问题修复中所述使用,以避免在上传大文件时低效使用内存(s.t.22 GiB文件约60秒。内存使用量恒定在13 MiB左右)


在Ubuntu中,您可以这样应用,

将文件保存在某个位置(临时),然后打开并发送到API
@martijn pieters的回答是正确的,但是我想为
数据=
添加一点上下文,并且在Flask服务器的另一端添加一点上下文,以防您试图上载文件和JSON

从请求端看,这是Martijn描述的:

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

r = requests.post(url, files=files, data=values)
然而,在Flask端(本文另一端的接收Web服务器),我必须使用
表单

@app.route("/sftp-upload", methods=["POST"])
def upload_file():
    if request.method == "POST":
        # the mimetype here isnt application/json
        # see here: https://stackoverflow.com/questions/20001229/how-to-get-posted-json-in-flask
        body = request.form
        print(body)  # <- immutable dict

这是不好的,因为服务器无法控制用户如何格式化请求;而
json=
将成为请求用户的习惯。

Hi,如何发送共享同一名称的多个文件?例如像“附件”。@William:您也可以使用一系列2值元组,这样您就可以重复使用字段名:
files=[('attachment',open('attachment1.txt','rb'),('attachment',open('attachment2.txt','rb'))]
。每个元组是一对键和值。你也可以使用
files={'file':('nameoffile',open('nameoffile','rb'),'Content-Type':'text/html','other header'),'file2':('nameoffile2','nameoffile2','rb'),'Content-Type':'application/xml','other header')}
但是如果使用files={},那么headers={'Content-Type':'blah}不得使用!->@martijn pieters:因为多部分/表单数据内容类型必须包含用于在post正文中删除部分的边界值。不设置内容类型标头可确保请求将其设置为正确的值。@MartijnPieters这不会有泄漏文件的风险吗?
请求
关闭它吗?@MattMessersmith:不,它没有关闭。如果要关闭文件,请使用打开(…)的
作为fobj:
并在
文件
映射中使用
fobj
。请求库是否自动关闭文件?您好,我使用此库已有一段时间了。问得好。你能帮我和其他人输入lsof | grep“filename”并与我们分享你的结果吗?谢谢:)使用
lsof
,似乎文件保持打开状态,或者至少我是这样解释以下结果的。之前,运行
open
lsof
表中没有关于
文件名的记录。然后在执行
open
后,会出现多条记录,并具有
read
访问权限。执行
请求.post
后,记录仍然存在,表明文件未关闭。
数据
变量的值是多少?它可以是用户名,我刚刚演示了如何将文件上载到RESTapis@martijn-pieters只是想看看你是否愿意在你的回答中包括这些,我会删除这个;这对于从客户机和服务器的“双方”角度得出这个答案的人来说可能很有用。
@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
      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)
files = {'upload_file': open('file.txt','rb')}
values = {'DB': 'photcat', 'OUT': 'csv', 'SHORT': 'short'}

r = requests.post(url, files=files, data=values)
@app.route("/sftp-upload", methods=["POST"])
def upload_file():
    if request.method == "POST":
        # the mimetype here isnt application/json
        # see here: https://stackoverflow.com/questions/20001229/how-to-get-posted-json-in-flask
        body = request.form
        print(body)  # <- immutable dict
r = requests.post(url, files=files, json=values). # No!