使用Azure Functions处理form-data多文件存储到Azure Blob空文件问题
问题根因
- 重复读取文件流:你在日志打印行已经调用了一次
file.stream.read(),文件流是一次性读取的,读取完成后指针移动到内容末尾,第二次调用file.stream.read()只会返回空字节,直接导致你拿到的contents为空,存入Blob的文件自然是0大小。 - 二进制文件解码错误:xlsx、pdf、png等格式都是二进制文件,使用
utf-8解码会直接破坏文件内容,甚至抛出解码异常,存储这类文件不需要做解码操作,直接保留原始bytes内容即可。
修正代码示例
以下提供两种常用的实现方案:
方案1:使用Azure Function Blob输出绑定(推荐)
首先需要在function.json中添加Blob输出绑定配置:
{ "name": "outputBlob", "type": "blob", "path": "你的容器名/{rand-guid}_{filename}", "connection": "你的Blob存储连接字符串配置名", "direction": "out" }
然后修改函数代码:
import azure.functions as func import logging # 输出绑定参数直接加在main函数入参里 def main(req: func.HttpRequest, outputBlob: func.Out[bytes]) -> func.HttpResponse: logging.info('Python HTTP trigger function processed a request.') try: files = req.files.values() file_count = 0 for file in files: filename = str(file.filename) # 只读取一次流,保留原始bytes格式 file_content = file.stream.read() logging.info(f"读取到文件:{filename},大小:{len(file_content)}字节") # 写入Blob,直接传bytes内容 outputBlob.set(file_content) file_count +=1 return func.HttpResponse(f"成功处理{file_count}个文件", status_code=200) except Exception as ex: logging.error(f"{str(type(ex))}: {str(ex)}") return func.HttpResponse(body=str(ex), status_code=400)
方案2:手动使用Blob SDK写入
如果需要自定义存储逻辑,可以手动调用Blob SDK实现:
首先安装依赖:pip install azure-storage-blob
代码示例:
import azure.functions as func import logging from azure.storage.blob import BlobClient import os def main(req: func.HttpRequest) -> func.HttpResponse: logging.info('Python HTTP trigger function processed a request.') # 从环境变量取Blob连接字符串 blob_conn_str = os.environ["你的Blob连接字符串配置名"] container_name = "你的容器名" try: files = req.files.values() file_count = 0 for file in files: filename = str(file.filename) file_content = file.stream.read() logging.info(f"读取到文件:{filename},大小:{len(file_content)}字节") # 实例化Blob客户端 blob_client = BlobClient.from_connection_string(blob_conn_str, container_name, filename) # 上传内容,直接传bytes blob_client.upload_blob(file_content, overwrite=True) file_count +=1 return func.HttpResponse(f"成功处理{file_count}个文件", status_code=200) except Exception as ex: logging.error(f"{str(type(ex))}: {str(ex)}") return func.HttpResponse(body=str(ex), status_code=400)
注意事项
- 处理多个文件时如果需要批量写入不同路径,可调整输出绑定为数组类型,或者循环实例化BlobClient指定不同的Blob路径
- 大文件上传建议开启Blob分块上传配置,避免内存溢出
内容的提问来源于stack exchange,提问作者NoName91
相关产品推荐
相关产品推荐

