【问题标题】:How to read contents of zip file in memory on a file upload in python?如何在python中上传文件时读取内存中zip文件的内容?
【发布时间】:2020-06-16 07:38:51
【问题描述】:

当用户上传文件时,我收到了一个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)

如您所见,这涉及到最终将 zip 文件中的内容放入内存的 3 个步骤。我想要的是获取zip文件的内容并直接加载到内存中。

我确实在堆栈溢出中发现了一些类似的问题,例如https://stackoverflow.com/a/2463819。但我不确定我在什么时候调用帖子中提到的这个操作

我怎样才能做到这一点?

注意:我在后端使用 django。 zip 中总会有一个 json 文件。

【问题讨论】:

    标签: python django file zip in-memory


    【解决方案1】:

    zipfile.ZipFile() 的第一个参数可以是文件对象而不是路径名。我认为 Django UploadedFile 对象支持这种用法,因此您可以直接从中读取,而不必复制到文件中。

    您也可以直接从 zip 存档中打开文件,而不是将其解压缩到文件中。

    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)
    

    【讨论】:

    • 谢谢老兄!这正是我一直在寻找的。为我节省了一些不必要的步骤。
    【解决方案2】:

    据我了解,@jason 想说的是here 是首先打开一个 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

    【讨论】:

    • 非常感谢,io.BytesIO() 为我工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 1970-01-01
    相关资源
    最近更新 更多