FastApi中UploadFile如何支持多次读取

错误代码如下

async def create_task(db: Session, model_uid: str, user_name: str, task_type: str, test_file: UploadFile):
    MinIOAccessor.put_object(test_file.file, test_file.size, test_file.content_type, test_file.content_type,os.path.join(config.minio_llm_eva_bucket,test_file.filename))
    eva_task(test_file.file.read(),test_file.filename)

在执行到eva_task函数的时候,传进去的参数test_file.file.read()总是0bytes,导致

pd.read_excel(file, engine='openpyxl')出现了一个很奇怪的报错:zipfile.BadZipFile: File is not a zip file

经过debug菜发现是file为空

再进一步排查发现是UploadFile不能连续读取两次,在读取过一次后,指针已经指向了文件的末尾

因此有如下两种解决办法:

方法一:将数据读取后存入BytesIO后续使用

test_file_1 = await test_file.read()
test_file_bytes = BytesIO(test_file_1)

方法二:再次读取时使用await myfile.seek(0) 移动到文件开头

UploadFile 的属性如下:

  • filename:上传文件名字符串(str),例如, myimage.jpg
  • content_type:内容类型(MIME 类型 / 媒体类型)字符串(str),例如,image/jpeg
  • file: SpooledTemporaryFile( file-like 对象)。其实就是 Python文件,可直接传递给其他预期 file-like 对象的函数或支持库。

UploadFile 支持以下 async 方法,(使用内部 SpooledTemporaryFile)可调用相应的文件方法。

  • write(data):把 data (str 或 bytes)写入文件;
  • read(size):按指定数量的字节或字符(size (int))读取文件内容;
  • seek(offset):移动至文件 offset (int)字节处的位置;
    • 例如,await myfile.seek(0) 移动到文件开头;
    • 执行 await myfile.read() 后,需再次读取已读取内容时,这种方法特别好用;
  • close():关闭文件。

因为上述方法都是 async 方法,要搭配「await」使用。

你可能感兴趣的:(fastapi,UploadFile)