问题:读取文件数据而不将其保存在Flask中
我正在编写我的第一个烧瓶应用程序。我正在处理文件上传,基本上我想要的是读取上传文件的数据/内容而不保存它,然后将其打印在结果页面上。是的,我假设用户总是上载文本文件。
这是我正在使用的简单上传功能:
@app.route('/upload/', methods=['GET', 'POST'])
def upload():
if request.method == 'POST':
file = request.files['file']
if file:
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
a = 'file uploaded'
return render_template('upload.html', data = a)
现在,我正在保存文件,但是我需要的是一个’a’变量来包含文件的内容/数据。
回答 0
FileStorage
包含stream
字段。该对象必须扩展IO或文件对象,因此它必须包含read
和其他类似方法。FileStorage
还扩展了stream
字段对象属性,因此您可以使用file.read()
代替file.stream.read()
。您也可以使用save
带有dst
参数as的参数StringIO
或其他IO或文件对象来复制FileStorage.stream
到另一个IO或文件对象。
请参阅文档:http : //flask.pocoo.org/docs/api/#flask.Request.files和http://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage。
回答 1
如果您要使用标准的Flask素材-如果上传的文件大小> 500kb,则无法避免保存临时文件。如果小于500kb,则将使用“ BytesIO”,它将文件内容存储在内存中;如果大于500kb,则将内容存储在TemporaryFile()中(如werkzeug文档中所述)。在这两种情况下,您的脚本都将阻塞,直到收到全部上传的文件为止。
我发现解决此问题的最简单方法是:
1)创建自己的类似于文件的IO类,在其中对传入数据进行所有处理
2)在您的脚本中,使用您自己的脚本覆盖Request类:
class MyRequest( Request ):
def _get_file_stream( self, total_content_length, content_type, filename=None, content_length=None ):
return MyAwesomeIO( filename, 'w' )
3)用您自己的替换Flask的request_class:
app.request_class = MyRequest
4)去喝点啤酒:)
回答 2
我试图做完全相同的事情,打开一个文本文件(实际上是熊猫的CSV文件)。不想复制它,只想打开它。WTF表单有一个不错的文件浏览器,但是随后它打开了文件并制作了一个临时文件,该文件以内存流的形式呈现。稍微做些工作,
form = UploadForm()
if form.validate_on_submit():
filename = secure_filename(form.fileContents.data.filename)
filestream = form.fileContents.data
filestream.seek(0)
ef = pd.read_csv( filestream )
sr = pd.DataFrame(ef)
return render_template('dataframe.html',tables=[sr.to_html(justify='center, classes='table table-bordered table-hover')],titles = [filename], form=form)
回答 3
我分享我的解决方案(假设所有内容都已配置为可以连接到烧瓶中的Google存储桶)
from google.cloud import storage
@app.route('/upload/', methods=['POST'])
def upload():
if request.method == 'POST':
# FileStorage object wrapper
file = request.files["file"]
if file:
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = app.config['GOOGLE_APPLICATION_CREDENTIALS']
bucket_name = "bucket_name"
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
# Upload file to Google Bucket
blob = bucket.blob(file.filename)
blob.upload_from_string(file.read())
我的帖子
回答 4
万一我们想将内存文件转储到磁盘上。可以使用此代码
if isinstanceof(obj,SpooledTemporaryFile):
obj.rollover()
回答 5
我们只是做了:
import io
from pathlib import Path
def test_my_upload(self, accept_json):
"""Test my uploads endpoint for POST."""
data = {
"filePath[]": "/tmp/bin",
"manifest[]": (io.StringIO(str(Path(__file__).parent /
"path_to_file/npmlist.json")).read(),
'npmlist.json'),
}
headers = {
'a': 'A',
'b': 'B'
}
res = self.client.post(api_route_for('/test'),
data=data,
content_type='multipart/form-data',
headers=headers,
)
assert res.status_code == 200
回答 6
在功能上
def handleUpload():
if 'photo' in request.files:
photo = request.files['photo']
if photo.filename != '':
image = request.files['photo']
image_string = base64.b64encode(image.read())
image_string = image_string.decode('utf-8')
#use this to remove b'...' to get raw string
return render_template('handleUpload.html',filestring = image_string)
return render_template('upload.html')
在html文件中
<html>
<head>
<title>Simple file upload using Python Flask</title>
</head>
<body>
{% if filestring %}
<h1>Raw image:</h1>
<h1>{{filestring}}</h1>
<img src="data:image/png;base64, {{filestring}}" alt="alternate" />.
{% else %}
<h1></h1>
{% endif %}
</body>