Не удается открыть и прочитать содержимое загруженного zip-файла с помощью FastAPI

#python #api #rest #multipartform-data #fastapi

#python #API #остальное #multipartform-данные #fastapi

Вопрос:

В настоящее время я разрабатываю для себя небольшой серверный проект с помощью фреймворка Python FastAPI. Я создал конечную точку, в которую пользователь должен иметь возможность загружать 2 файла, в то время как первый представляет собой zip-файл (который содержит X .xmls), а последний — обычный XML-файл.

Код выглядит следующим образом:

 @router.post("/sendxmlinzip/")
def create_upload_files_with_zip(files: List[UploadFile] = File(...)):
    if not len(files) == 2:
        raise Httpex.EXPECTEDTWOFILES
    my_file = files[0].file
    zfile = zipfile.ZipFile(my_file, 'r')
    filelist = []
    for finfo in zfile.infolist():
        print(finfo)
        ifile = zfile.open(finfo)
        line_list = ifile.readlines()
        print(line_list)
  

При этом должно быть напечатано содержимое файлов, которые находятся в ZIP-файле, но возникает исключение

Ошибка атрибута: объект ‘SpooledTemporaryFile’ не имеет атрибута ‘seekable’

В строке ifile = zfile.open(finfo)

После примерно 3-дневных исследований с множеством проб и ошибок, попыток использовать различные функции, такие как .read() или .extract(), я сдался. Поскольку в документах python буквально указано, что это должно быть возможно таким образом…

Для тех, кто не знает о FastAPI, это серверная часть fw для веб-сервисов Restful, использующая структуру данных starlette для uploadFile. Пожалуйста, простите меня, если я заметил что-то ОЧЕНЬ очевидное, но я буквально пытался проверить каждый уголок, что могло быть возможной причиной ошибки, такой как:

  • Проверьте, возможна ли другая реализация
  • Проверьте правильность .zip-файла
  • Убедитесь, что я прикрепил правильный файл (lol)
  • Отладка, чтобы увидеть, действительно ли фактические данные, поступающие на серверную часть, являются ZIP-файлом

Комментарии:

1. Я также попытался запустить ТОТ ЖЕ фрагмент кода, используя только ЛОКАЛЬНЫЙ zip-файл, и у меня все получилось отлично, поэтому я считаю, что проблема связана со структурой данных Starlette… Кажется, я просто не могу найти обходной путь для этого

2. Это правда, что у a SpooledTemporaryFile нет seekable метода, но я не уверен, что это проблема. Вы могли бы попытаться обойти проблему, записав содержимое my_file в локальный TemporaryFile файл, а затем zipfile.ZipFile , возможно, открыв его.

Ответ №1:

Это известная ошибка Python:

SpooledTemporaryFile не полностью удовлетворяет аннотации для IOBase. А именно, seekable , readable , и writable отсутствуют.

Это было обнаружено при поиске файла lzma с поддержкой SpooledTemporaryFile.

Как предложил @larsks в своем комментарии, я бы попробовал записать содержимое буферного файла в новый TemporaryFile , а затем поработать с ним. Пока ваши файлы не слишком большие, это должно работать так же хорошо.

Комментарии:

1. Спасибо за короткий и лаконичный ответ! Работал отлично

Ответ №2:

Это мой обходной путь

 with zipfile.ZipFile(io.BytesIO(file.read()), 'r') as zip: