问题: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.
仅当文件为空时才会出现。因此,我对如何成功发送文件感到困惑。我知道该文件有效,因为如果我访问此网站并手动填写表格,它将返回一个很好的匹配对象列表,这就是我想要的。我非常感谢所有提示。
其他一些相关的线程(但不能回答我的问题):
回答 0
如果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
字段设置为内容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')}
这将设置备用文件名和内容类型,而忽略可选的标题。
如果您要从文件中提取整个POST正文(未指定其他字段),则不要使用files
参数,只需将文件直接发布为即可data
。然后,您可能还需要设置Content-Type
标头,否则将不会设置任何标头。请参阅Python请求-文件中的POST数据。
回答 1
(2018)新的python请求库简化了此过程,我们可以使用’files’变量表示我们要上传经过多部分编码的文件
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}
r = requests.post(url, files=files)
r.text
回答 2
客户上传
如果要使用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表单数据解析来解决“ 大文件上传占用内存 ”的问题,以避免在大文件上传时(约60秒内无效使用 st 22 GiB文件。) 13 MiB。)。
@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
回答 3
在Ubuntu中,您可以采用这种方式,
将文件保存在某个位置(临时),然后打开并发送给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)