You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过FastAPI从Azure Storage Blob下载XLSX文件?遇500错误求助

问题原因分析

你的代码返回500错误的核心问题有两个:

  1. FastAPI的FileResponse的content参数不接受远程URL,它仅支持本地文件路径、类文件对象或字节流,直接传入Blob URL会触发内部处理错误。
  2. 即使Blob URL能被FastAPI处理,私有容器下的Blob默认没有公开访问权限,浏览器直接访问该URL会返回403,也无法完成下载。
解决方案

以下提供两种可行的实现方式,根据你的场景选择:

方案一:生成带SAS令牌的Blob URL,返回重定向

这种方式让浏览器直接跳转到Azure Storage的授权下载地址,FastAPI无需处理文件内容,效率更高,适合无需对文件内容做额外处理的场景。

from fastapi import RedirectResponse, JSONResponse
from azure.storage.blob import BlobServiceClient, generate_blob_sas, BlobSasPermissions
from datetime import datetime, timedelta

def download_blob(blob_service_client, filename: str, container: str):
    try:        
        blob_client = blob_service_client.get_blob_client(container=container, blob=filename)
        # 生成有效期1小时的只读SAS令牌
        sas_token = generate_blob_sas(
            account_name=blob_service_client.account_name,
            container_name=container,
            blob_name=filename,
            account_key=blob_service_client.credential.account_key,
            permission=BlobSasPermissions(read=True),
            expiry=datetime.utcnow() + timedelta(hours=1)
        )
        # 拼接带SAS授权的完整Blob URL
        authorized_blob_url = f"{blob_client.url}?{sas_token}"
        # 返回重定向,让浏览器直接访问授权URL下载
        return RedirectResponse(url=authorized_blob_url, status_code=302)
    except Exception as e:
        # 生产环境建议隐藏具体错误信息,仅返回通用提示
        return JSONResponse(content={"message": f"下载失败: {str(e)}"}, status_code=500)

方案二:读取Blob内容为字节流,返回FileResponse

这种方式FastAPI先将Blob内容读取到内存,再返回给客户端,适合需要对文件内容做修改、加密等处理,或者不想暴露Blob存储地址的场景。

from fastapi import FileResponse, JSONResponse
from azure.storage.blob import BlobServiceClient
from io import BytesIO

def download_blob(blob_service_client, filename: str, container: str):
    try:        
        blob_client = blob_service_client.get_blob_client(container=container, blob=filename)
        # 读取Blob内容到字节流
        blob_byte_data = blob_client.download_blob().readall()
        # 用BytesIO包装字节流,作为FileResponse的内容
        return FileResponse(
            content=BytesIO(blob_byte_data),
            # XLSX格式的标准媒体类型
            media_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            filename=filename  # 可自定义下载后的文件名,比如改为"Test.xlsx"
        )
    except Exception as e:
        return JSONResponse(content={"message": f"下载失败: {str(e)}"}, status_code=500)
额外注意事项
  • 确保你的Azure Storage凭证(账户密钥或连接字符串)拥有Blob的读取权限,避免因权限不足触发错误。
  • 生产环境中不建议直接硬编码账户密钥,推荐使用Azure AD身份验证或托管标识(Managed Identity)访问Blob存储,提升安全性。

内容的提问来源于stack exchange,提问作者Himanshu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:30:56