#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:
SpooledTemporaryFile не полностью удовлетворяет аннотации для IOBase. А именно,
seekable
,readable
, иwritable
отсутствуют.Это было обнаружено при поиске файла lzma с поддержкой SpooledTemporaryFile.
Как предложил @larsks в своем комментарии, я бы попробовал записать содержимое буферного файла в новый TemporaryFile
, а затем поработать с ним. Пока ваши файлы не слишком большие, это должно работать так же хорошо.
Комментарии:
1. Спасибо за короткий и лаконичный ответ! Работал отлично
Ответ №2:
Это мой обходной путь
with zipfile.ZipFile(io.BytesIO(file.read()), 'r') as zip: