读取文件数据而不将其保存在Flask中

时间:2013-11-16 06:35:21

标签: python 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'变量来包含文件的内容/数据..任何想法?

6 个答案:

答案 0 :(得分:98)

FileStorage包含stream字段。此对象必须扩展IO或文件对象,因此它必须包含read和其他类似方法。 FileStorage还扩展了stream字段对象属性,因此您只需使用file.read()代替file.stream.read()。您还可以将save参数与dst参数一起用作StringIO或其他IO或文件对象,以将FileStorage.stream复制到另一个IO或文件对象。

请参阅文档:http://flask.pocoo.org/docs/api/#flask.Request.fileshttp://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage

答案 1 :(得分:7)

如果你想使用标准的Flask东西 - 如果上传的文件大小是>则无法避免保存临时文件。 500KB。如果它小于500kb - 它将使用“BytesIO”,它将文件内容存储在内存中,如果它超过500kb - 它将内容存储在TemporaryFile()中(如werkzeug documentation中所述)。在这两种情况下,您的脚本都会阻止,直到收到整个上传文件为止。

我找到的最简单的解决方法是:

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 :(得分:1)

我试图做完全相同的事情,打开一个文本文件(实际上是熊猫的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 :(得分:1)

我分享我的解决方案(假设所有内容都已配置为连接到烧瓶中的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())

我的帖子

Direct to Google Bucket in flask

答案 4 :(得分:0)

万一我们想将内存文件转储到磁盘上。可以使用此代码

  if isinstanceof(obj,SpooledTemporaryFile):
    obj.rollover()

答案 5 :(得分:0)

我们只是做了:

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
相关问题