如何在Python中上传文件时从内存中读取zip文件的内容?

3

当用户上传文件时,我会收到一个zip文件。这个zip文件实际上包含了一个json文件,我想要在不必先创建zip文件、解压缩它,然后读取内部文件内容的情况下读取和处理它。

目前我只有以下更长的处理过程:

import json
import zipfile

@csrf_exempt
def get_zip(request):
    try:
        if request.method == "POST":
            try:
                client_file = request.FILES['file']
                file_path = "/some/path/"
                # first dump the zip file to a directory
                with open(file_path + '%s' % client_file.name, 'wb+') as dest:
                        for chunk in client_file.chunks():
                            dest.write(chunk)

                # unzip the zip file to the same directory 
                with zipfile.ZipFile(file_path + client_file.name, 'r') as zip_ref:
                    zip_ref.extractall(file_path)

                # at this point we get a json file from the zip say `test.json`
                # read the json file content
                with open(file_path + "test.json", "r") as fo:
                    json_content = json.load(fo)
                    doSomething(json_content)
                return HttpResponse(0)

            except Exception as e:
                return HttpResponse(1)

如您所见,这涉及到3个步骤才能最终将zip文件中的内容加载到内存中。我想要的是直接获取zip文件的内容并直接加载到内存中。
我在stackoverflow上找到了一些类似的问题,比如这个https://dev59.com/ZHE95IYBdhLWcg3wE56C#2463819。但我不确定在何时调用此操作。
我该如何实现这个功能?
注意:我正在使用django作为后端。zip文件中始终会有一个json文件。
2个回答

6
据我所了解,@jason在这里所要表达的是首先像你在这里的代码中一样打开zipFile:with zipfile.ZipFile(file_path + client_file.name, 'r') as zip_ref:
class zipfile.ZipFile(file[, mode[, compression[, allowZip64]]])

  Open a ZIP file, where file can be either a path to a file (a string) or a file-like object.

然后使用BytesIO读取文件对象的字节数。但是上面你是以r模式读取,而不是rb模式。所以请按以下方式进行更改。

with open(filename, 'rb') as file_data:
    bytes_content = file_data.read()
    file_like_object = io.BytesIO(bytes_content)
    zipfile_ob = zipfile.ZipFile(file_like_object)

现在zipfile_ob可以从内存中访问。

2
非常感谢,io.BytesIO() 对我很有帮助。 - Nikhil VJ
你好,是否有可能在不提取所有文件的情况下即时解压缩一个zip文件中的文件? - EdwinMald
我认为是这样的...在这里检查一下:https://note.nkmk.me/en/python-zipfile/,在标题“从ZIP文件中提取单个文件”下有其他方法。 - AzyCrw4282

6
< p > zipfile.ZipFile() 的第一个参数可以是文件对象,而不是路径名。我认为 Django 的 UploadedFile 对象支持此用法,因此您可以直接从中读取,而无需复制到文件中。< /p > < p > 您还可以直接从 zip 存档中打开文件,而不必将其提取到文件中。< /p >
import json
import zipfile

@csrf_exempt
def get_zip(request):
    try:
        if request.method == "POST":
            try:
                client_file = request.FILES['file']
                # unzip the zip file to the same directory 
                with zipfile.ZipFile(client_file, 'r') as zip_ref:
                    first = zip_ref.infolist()[0]
                    with zip_ref.open(first, "r") as fo:
                        json_content = json.load(fo)
                doSomething(json_content)
                return HttpResponse(0)

            except Exception as e:
                return HttpResponse(1)

谢谢伙计!这正是我在寻找的。为我节省了一些不必要的步骤。 - Souvik Ray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接