I am uploading a zip file with Fast API and it takes in the files as a SpooledTemporaryFile. I have been trying to copy that file onto disk. I have attempted various things; the two I feel I have made progress in are down below.
I have attempted to use zipfile.Zipfile, when I turn it into one I am unable to unzip it because it says it is not a zip.
I also uploaded a single file that is not zipped and turned the SpooledTemporaryFile into _io.BytesIO, however, when I try to read the content of a single file (not zipped) it returned empty byte (b'').
I'm actually working on something similar and ran into the same issues. The solution I came up with was to use the File option (not the UploadFile one), write the input to another file, then perform the unzip.
Here's my implementation using a TemporaryDirectory and separate directories for input and unzipped files:
@router.post("/test_file/unzip")
def unzip_upload(file: bytes = File(...)):
with tempfile.TemporaryDirectory() as temp_dir:
os.chdir(temp_dir)
os.mkdir('input')
os.mkdir('unzipped')
with open("input/zip_file.zip", 'wb') as new_file:
new_file.write(file)
# print(f"output of listdir for /input {os.listdir(temp_dir + '/input')}")
with zipfile.ZipFile("input/zip_file.zip") as zip_file:
print(f"files in zip: {zip_file.namelist()}")
zip_file.extractall('unzipped')
unzipped_files = os.listdir('unzipped')
return {"unzipped files": unzipped_files}
If you need to use the UploadFile option, I got this to work:
@router.post("/test_uploadfile/unzip")
def unzip_upload(file: UploadFile = File(...)):
with tempfile.TemporaryDirectory() as temp_dir:
os.chdir(temp_dir)
os.mkdir('input')
os.mkdir('unzipped')
with open("input/zip_file.zip", 'wb') as new_file:
new_file.write(file.file._file.getvalue())
# print(f"output of listdir for /input {os.listdir(temp_dir + '/input')}")
with zipfile.ZipFile("input/zip_file.zip") as zip_file:
print(f"files in zip: {zip_file.namelist()}")
zip_file.extractall('unzipped')
unzipped_files = os.listdir('unzipped')
return {"unzipped files": unzipped_files}