Read a zip file sent to a flask server without storing it on disk

喜夏-厌秋 提交于 2020-08-10 18:04:24

问题


I would like to read all the files in a zip file of a specific type sent to a flask server via a form post request without having to store the zip file on disk.


回答1:


First, get the code to get the zip file

from flask import Flask, request
app = Flask(__name__)

@app.route("/",methods=["GET"])
def page_name_get(): 
    return """<form action="." method="post" enctype=multipart/form-data>
        <input type="file" accept="application/zip" name="data_zip_file" accept="application/zip" required>
         <button type="submit">Send zip file!</button>
        </form>"""
app.run()

This is how the post request function should look like

import zipfile

@app.route("/",methods=["POST"])
def page_name_post():
    file = request.files['data_zip_file']  
    file_like_object = file.stream._file  
    zipfile_ob = zipfile.ZipFile(file_like_object)
    file_names = zipfile_ob.namelist()
    # Filter names to only include the filetype that you want:
    file_names = [file_name for file_name in file_names if file_name.endswith(".txt")]
    files = [(zipfile_ob.open(name).read(),name) for name in file_names]
    return str(files)

Now I will go over this line by line

file = request.files['data_zip_file'] First, you need to get the file object from the request this is is an instance of the werkzeug.datastructures.FileStorage class.

file_like_object = file.stream._file here you first take the stream attribute of the werkzeug.datastructures.FileStorage this is the input stream of the file. This will return an instance of tempfile.SpooledTemporaryFile a class used for temporary files. From that instance, you take the ._file attribute. This will return an instance of tempfile._TemporaryFileWrapper This is enough like an io.BytesIO to be understood by the zipfile.ZipFile class.

zipfile_ob = zipfile.ZipFile(file_like_object) here you create the zipfile.Zipfile object

Now you should be able to do pretty much everything you would want to do with the zip. To select a file from the zip use the zipfile_ob.open() method and pass in the path to the file you want to open.

To get those paths we use file_names = zipfile_ob.namelist() this will return a list with strings of all the paths to all the files and directories in the zip.

You can then filter those names with file_names = [file_name for file_name in file_names if file_name.endswith(".txt")]

All those paths you want are now in file_names. Then you can extract the data of those files using the open function.

files = [(zipfile_ob.open(name).read(),name) for name in file_names]

In the example given I keep the paths to the file in the final list but if you don't want that you can use:

files = [zipfile_ob.open(name).read() for name in file_names] or use some other way to go over the file. If you want more info about the files there is also the infolist() method that can be used instead of the namelist() this will return a list of ZipInfo Objects instead of a list of just strings. These objects hold some more data about all the files.



来源:https://stackoverflow.com/questions/60643857/read-a-zip-file-sent-to-a-flask-server-without-storing-it-on-disk

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!