Đọc dữ liệu tệp mà không cần lưu trong Flask


112

Tôi đang viết ứng dụng bình đầu tiên của mình. Tôi đang xử lý việc tải lên tệp và về cơ bản những gì tôi muốn là đọc dữ liệu / nội dung của tệp đã tải lên mà không cần lưu nó và sau đó in nó trên trang kết quả. Có, tôi giả định rằng người dùng luôn tải lên tệp văn bản.

Đây là chức năng tải lên đơn giản mà tôi đang sử dụng:

@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)

Ngay bây giờ, tôi đang lưu tệp, nhưng điều tôi cần là biến 'a' đó để chứa nội dung / dữ liệu của tệp .. có ý kiến ​​gì không?

Câu trả lời:


137

FileStoragestreamtrường chứa . Đối tượng này phải mở rộng IO hoặc đối tượng tệp, vì vậy nó phải chứa readvà các phương thức tương tự khác. FileStoragecũng mở rộng streamcác thuộc tính đối tượng trường, vì vậy bạn chỉ có thể sử dụng file.read()thay thế file.stream.read(). Ngoài ra, bạn có thể sử dụng saveđối số với dsttham số là StringIOhoặc IO hoặc đối tượng tệp khác để sao chép FileStorage.streamsang IO hoặc đối tượng tệp khác.

Xem tài liệu: http://flask.pocoo.org/docs/api/#flask.Request.fileshttp://werkzeug.pocoo.org/docs/datastructures/#werkzeug.datastructures.FileStorage .


1
ví dụ nhanh:file = request.files.get('file') filetype = magic.from_buffer(file.read(1024))
endolith

7
xin chào @ user2480542. Tôi đang gặp phải vấn đề tương tự. Bạn có thể mô tả cách bạn đọc nội dung của tệp do khách hàng tải lên không? Tôi đang gọi file.read () nhưng không nhận được gì. Cảm ơn!
tmthyjames

1
@tmthyjames f = request.files['file']đặt tệp đã tải lên (trong yêu cầu) thành var ("f"). Sau đó, f.read()sau đó hoạt động bằng cách sử dụng mã trên. khi nào thì print f.read()tôi nhận được những thứ rác rưởi trong thiết bị đầu cuối. Hy vọng rằng sẽ giúp.
Marc

6
Nếu bạn đang tải lên một tập tin và có một dòng nhị phân, bạn có thể dễ dàng chuyển đổi nó thành một dòng văn bản bằng cách gói nó trong TextIOWrapper: mystring = TextIOWrapper(binary_stream)
Dutch Masters

6
f.read()không mang lại bất cứ điều gì cho tôi quá. Gọi điện trước f.seek(0)đã giúp tôi.
w177us

11

Nếu bạn muốn sử dụng nội dung Flask tiêu chuẩn - không có cách nào để tránh lưu tệp tạm thời nếu kích thước tệp tải lên> 500kb. Nếu nhỏ hơn 500kb - nó sẽ sử dụng "BytesIO", nơi lưu trữ nội dung tệp trong bộ nhớ và nếu lớn hơn 500kb - nó sẽ lưu nội dung trong TemporaryFile () (như đã nêu trong tài liệu werkzeug ). Trong cả hai trường hợp, tập lệnh của bạn sẽ chặn cho đến khi nhận được toàn bộ tệp đã tải lên.

Cách dễ nhất để giải quyết vấn đề này mà tôi đã tìm thấy là:

1) Tạo lớp IO giống tệp của riêng bạn, nơi bạn thực hiện tất cả quá trình xử lý dữ liệu đến

2) Trong tập lệnh của bạn, ghi đè lớp Yêu cầu bằng lớp của riêng bạn:

class MyRequest( Request ):
  def _get_file_stream( self, total_content_length, content_type, filename=None, content_length=None ):
    return MyAwesomeIO( filename, 'w' )

3) Thay thế lớp request_class của Flask bằng lớp của riêng bạn:

app.request_class = MyRequest

4) Đi uống một chút bia :)


0

Tôi đang cố gắng làm điều tương tự, mở một tệp văn bản (thực tế là CSV cho Gấu trúc). Không muốn tạo một bản sao của nó, chỉ muốn mở nó ra. Form-WTF có một trình duyệt tệp đẹp, nhưng sau đó nó mở tệp và tạo một tệp tạm thời, tệp này trình bày dưới dạng một luồng bộ nhớ. Với một công việc nhỏ,

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) 

0

Tôi chia sẻ giải pháp của mình (giả sử mọi thứ đã được định cấu hình để kết nối với google bucket trong flask)

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())

Bài viết của tôi

Trực tiếp đến Google Bucket trong flask


-1

Trong trường hợp chúng ta muốn kết xuất tập tin trong bộ nhớ vào đĩa. Mã này có thể được sử dụng

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

-1

Đơn giản là chúng tôi đã làm:

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

-1

trong chức năng

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')

trong tệp 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>

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.