Как прочитать содержимое zip-файла в памяти при загрузке файла в python? - PullRequest
0 голосов
/ 04 марта 2020

У меня есть файл 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 и загрузить его непосредственно в память.

Я обнаружил, что при переполнении стека я нашел несколько похожих вопросов, таких как этот { ссылка }. Но я не уверен, в какой момент я вызову эту операцию, упомянутую в посте

Как мне этого добиться?

Примечание: Я использую django в бэкенд. В архиве всегда будет один json файл.

Ответы [ 2 ]

1 голос
/ 04 марта 2020

Первым аргументом 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)
1 голос
/ 04 марта 2020

Насколько я понимаю, @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 можно получить доступ.

...