使用Azure upload_blob上传Starlette UploadFile报错:非路径类对象
问题:Starlette UploadFile 上传到 Azure Blob Storage 报错
通过客户端向Python编写的GraphQL服务器发送multipart文件,服务器接收为<starlette.datastructures.UploadFile object>。尝试使用Azure Storage的upload_blob方法上传时,出现错误:expected str, bytes or os.PathLike object, not UploadFile。已按照Starlette文档使用file.read()读取文件内容,以下是实现代码及报错堆栈。
原实现代码
@mutation.field("fileUpload") async def resolve_fileUpload(_, info, file): print(f"File - {file.filename}") bytes_file = await file.read() container_client = blob_service_client.get_container_client( '4160000000') if not container_client.exists(): container_client.create_container() with open(file, "rb") as file: result = container_client.upload_blob( name='avatar', data=bytes_file) return { "status": 200, "error": "", "fileUrl": "www.test.com" }
报错堆栈信息
[2023-06-07T16:30:47.294Z] expected str, bytes or os.PathLike object, not UploadFile GraphQL request:3:3 2 | __typename 3 | fileUpload(file: $file) { | ^ 4 | __typename Traceback (most recent call last): File "C:\Users\sumch\AppData\Local\Programs\Python\Python310\lib\site-packages\graphql\execution\execute.py", line 528, in await_result return_type, field_nodes, info, path, await result File "C:\Users\sumch\OneDrive\Projects\Flutter Projects\bol\bol-api\bol-api\user_operations\mutations.py", line 86, in resolve_fileUpload with open(file, "rb") as file: TypeError: expected str, bytes or os.PathLike object, not UploadFile The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\sumch\AppData\Local\Programs\Python\Python310\lib\site-packages\graphql\execution\execute.py", line 1036, in await_result return build_response(await result, errors) # type: ignore File "C:\Users\sumch\AppData\Local\Programs\Python\Python310\lib\site-packages\graphql\execution\execute.py", line 403, in set_result results[response_name] = await result File "C:\Users\sumch\AppData\Local\Programs\Python\Python310\lib\site-packages\graphql\execution\execute.py", line 535, in await_result self.handle_field_error(error, return_type) File "C:\Users\sumch\AppData\Local\Programs\Python\Python310\lib\site-packages\graphql\execution\execute.py", line 569, in handle_field_error raise error File "C:\Users\sumch\AppData\Local\Programs\Python\Python310\lib\site-packages\graphql\execution\execute.py", line 528, in await_result return_type, field_nodes, info, path, await result File "C:\Users\sumch\OneDrive\Projects\Flutter Projects\bol\bol-api\bol-api\user_operations\mutations.py", line 86, in resolve_fileUpload with open(file, "rb") as file: graphql.error.graphql_error.GraphQLError: expected str, bytes or os.PathLike object, not UploadFile GraphQL request:3:3 2 | __typename 3 | fileUpload(file: $file) { | ^ 4 | __typename
错误原因
报错核心是代码中with open(file, "rb") as file:这一行:open()函数仅接受文件路径字符串、字节或路径对象,无法直接处理UploadFile实例。而且你已经通过await file.read()将文件内容读取到bytes_file变量中,这段open操作完全多余,反而引发了类型错误。
另外,Azure的upload_blob方法本身支持直接传入字节数据,无需额外打开文件。
修正后的代码
@mutation.field("fileUpload") async def resolve_fileUpload(_, info, file): print(f"File - {file.filename}") bytes_file = await file.read() container_client = blob_service_client.get_container_client('4160000000') if not container_client.exists(): container_client.create_container() # 直接使用读取到的字节数据上传,移除多余的open操作 result = container_client.upload_blob(name='avatar', data=bytes_file) return { "status": 200, "error": "", "fileUrl": "www.test.com" }
大文件优化方案(可选)
如果处理大文件,为避免一次性将文件内容加载到内存,可以直接传入UploadFile的底层类文件对象实现流式上传:
@mutation.field("fileUpload") async def resolve_fileUpload(_, info, file): print(f"File - {file.filename}") container_client = blob_service_client.get_container_client('4160000000') if not container_client.exists(): container_client.create_container() # 直接传入UploadFile的底层文件对象,流式上传节省内存 result = container_client.upload_blob(name='avatar', data=file.file) return { "status": 200, "error": "", "fileUrl": "www.test.com" }
内容的提问来源于stack exchange,提问作者Sumchans
相关产品推荐
相关产品推荐

