[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’변수가 필요합니다. 어떤 아이디어가 있습니까?



답변

FileStoragestream필드를 포함 합니다. 이 개체는 IO 또는 파일 개체를 확장해야하므로 read및 기타 유사한 메서드를 포함해야합니다 . FileStorage또한 stream필드 개체 ​​속성을 확장 하므로 file.read()대신 사용할 수 있습니다 file.stream.read(). 또한 매개 변수 save와 함께 인수를 사용 하거나 다른 IO 또는 파일 개체를 사용하여 다른 IO 또는 파일 개체로 복사 할 수 있습니다.dstStringIOFileStorage.stream

문서 참조 : http://flask.pocoo.org/docs/api/#flask.Request.fileshttp://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .


답변

표준 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) 가서 맥주 마시기 🙂


답변

나는 똑같은 일을하고 텍스트 파일 (실제로는 팬더 용 CSV)을 열려고했습니다. 복사본을 만들고 싶지 않고 열어보고 싶을뿐입니다. form-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) 


답변

내 솔루션을 공유합니다 (모든 것이 플라스크의 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())

내 게시물

플라스크의 Google 버킷으로 안내


답변

메모리 파일을 디스크에 덤프하려는 경우. 이 코드를 사용할 수 있습니다.

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


답변

우리는 간단히 :

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


답변

기능상

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>