如何在 Flask 中通过 gzip 解压缩 FileStorage 对象

How to decompress a FileStorage object over gzip in Flask

我正在通过 HTTP multipart/form-data POST 请求向我的 Flask 应用程序发送一个压缩文件(使用 gzip 压缩)。该请求工作正常,当我将密钥的值打印到控制台时,它会打印:<FileStorage: 'compressed.zip' ('application/zip')>。这是使用 Windows zip compressed 压缩的,但将使用 application/gzip 类型压缩。 compressed.zip 文件的密钥称为 compressed。我的问题是如何解压缩 gzip 文件,然后将 FileStorage 对象存储到后端的特定路径?这是我目前拥有的代码:

from flask import request, Blueprint, make_response
import gzip
blueprint = Blueprint("blueprint", __name__)

@blueprint.route("/compressed-post", methods=["POST"])
def compressed_post():
    if request.method == "POST":
        file = request.files["compressed"]
        print(file)
        return make_response("", 200)
    else:
        return make_response("", 400)

尝试使用以下方法:

from flask import request, Blueprint, make_response
from zipfile import ZipFile
import gzip
blueprint = Blueprint("blueprint", __name__)

@blueprint.route("/compressed-post", methods=["POST"])
def compressed_post():
    if request.method == "POST":
        file = request.files["compressed"]
        print(file)
        file_name = file.filename
        with ZipFile(file_name, 'r') as zip: 
            # printing all the contents of the zip file 
            zip.printdir() 
  
            # extracting all the files 
            print('Extracting all the files now...') 
            zip.extractall(<path_to_destination_dir>) 
            print('Done!')
        
        return make_response("", 200)
    else:
        return make_response("", 400)

有关 zip 的更多详细信息,请参阅:ZipFile and extractall()

有关 FileStorage 对象的更多详细信息,请参阅:FileStorage

如果您需要更多信息来存储 FileStorage 对象: 将文件保存到目标路径或文件对象。如果目标是一个文件对象,你必须在调用后自己关闭它。缓冲区大小是复制过程中保存在内存中的字节数。默认为 16KB。

看到这个:save

希望对您有所帮助。

鉴于您的代码片段...

@blueprint.route("/compressed-post", methods=["POST"])
def compressed_post():
    if request.method == "POST":
        file = request.files["compressed"]

...你只需要将 file._file 传递给 ZipFile 构造函数,因为 ZipFile 需要一个类似文件的对象(或完整路径,我们这样做此处没有,因为文件尚未保存到磁盘)。

然后,您可以使用ZipFiles extractAll方法将文件解压到您喜欢的路径。

另见

https://docs.python.org/3/library/zipfile.html#zipfile.ZipFile.extractall

所以,完整的代码应该是这样的:

from flask import request, Blueprint, make_response
import gzip
from zipfile import ZipFile
blueprint = Blueprint("blueprint", __name__)

@blueprint.route("/compressed-post", methods=["POST"])
def compressed_post():
    if request.method == "POST":
        file = request.files["compressed"]
        zip_handle = ZipFile(file._file)
        zip_handle.extractall(CHOOSE_YOUR_PATH)
        zip_handle.close()
        return make_response("", 200)
    else:
        return make_response("", 400)
        
如果您更喜欢 with 语法,

ZipFile 也有一个上下文管理器。

提醒一句:file._file 中的 _ 表明,_file 不是 public 接口的一部分,将来可能会更改。