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

如何使用Azure Function将xlsb转xlsx?部署故障求助

问题描述

我开发了一个将xlsb文件转换为xlsx的函数,本地测试成功,但部署到Azure Portal运行时出现报错:

Result: Failure Exception: OSError: [Errno 30] Read-only file system: 'TEST.xlsx'

查资料后得知,基于Linux的Python版Azure Function只能把文件保存到临时目录,于是修改了函数,结果又出现新错误:

Result: Failure Exception: FileNotFoundError: [Errno 2] No such file or directory: '/tmp/TEST.xlsb'

现在需要实现基于Blob触发的Azure Function,把Blob容器里的xlsb文件转换成xlsx后保存回原容器。以下是我的两次尝试代码:

初次尝试代码

import os
import logging
import pandas as pd
#from io import BytesIO
import azure.functions as func
from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient
 
app = func.FunctionApp()
 
@app.blob_trigger(arg_name="myblob", path="{containerName}/{name}.xlsb",
                               connection="BlobStorageConnectionString")
def blob_trigger(myblob: func.InputStream):
    logging.info(f"Python blob trigger function processed blob"
                f"Name: {myblob.name}"
                f"Blob Size: {myblob.length} bytes")
   
    accountName = "name"
    accountKey = "key"
    connectionString = f"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net"
   
    containerName = "{containerName}"
    inputBlobname = myblob.name.replace({containerName}, "")
    outputBlobname = inputBlobname.replace(".xlsb", ".xlsx")
 
    blob_service_client = BlobServiceClient.from_connection_string(connectionString)
    container_client = blob_service_client.get_container_client(containerName)
    blob_client = container_client.get_blob_client(inputBlobname)
    blob = BlobClient.from_connection_string(conn_str=connectionString, container_name=containerName, blob_name=outputBlobname)
 
    df = pd.read_excel(blob_client.download_blob().readall(), engine="pyxlsb")
 
    df.to_excel(outputBlobname, index=False)
 
    with open(outputBlobname, "rb") as data:
        blob.upload_blob(data, overwrite=True)

修改后代码

import os
import logging
import pandas as pd
#from io import BytesIO
import azure.functions as func
from azure.storage.blob import BlobServiceClient, ContainerClient, BlobClient

app = func.FunctionApp()

@app.blob_trigger(arg_name="myblob", path="{containerName}/{name}.xlsb",
                               connection="BlobStorageConnectionString") 
def blob_trigger(myblob: func.InputStream):
    logging.info(f"Python blob trigger function processed blob"
                f"Name: {myblob.name}"
                f"Blob Size: {myblob.length} bytes")
    
    accountName = "name"
    accountKey = "key"
    connectionString = f"DefaultEndpointsProtocol=https;AccountName={accountName};AccountKey={accountKey};EndpointSuffix=core.windows.net"
    
    containerName = "{containerName}"
    inputBlobname = myblob.name.replace({containerName}, "")
    localBlobname = "/tmp/" + inputBlobname
    outputBlobname = inputBlobname.replace(".xlsb", ".xlsx")

    blob_service_client = BlobServiceClient.from_connection_string(connectionString)
    container_client = blob_service_client.get_container_client(containerName)
    blob_client = container_client.get_blob_client(inputBlobname)
    blob = BlobClient.from_connection_string(conn_str=connectionString, container_name=containerName, blob_name=outputBlobname)

    df = pd.read_excel(blob_client.download_blob().readall(), engine="pyxlsb")

    df.to_excel("/tmp/" + outputBlobname, index=False)
    ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))

    with open(file = os.path.join(ROOT_DIR, localBlobname), mode="rb") as data:
        blob.upload_blob(data, overwrite=True)
错误分析
  1. 第一个错误:Linux环境的Azure Function默认文件系统只读,不能直接在当前目录创建文件,必须使用/tmp临时目录。
  2. 第二个错误:修改后的代码逻辑混乱——既没把源xlsb文件下载到/tmp,却尝试读取该路径的文件;硬编码{containerName}无法正确获取触发器传入的容器名,导致inputBlobname路径处理错误;最后要上传的应该是生成的xlsx文件,不是源xlsb文件。
解决方案

直接用内存流处理文件转换,避免写入临时文件,同时修正容器名和文件名的获取逻辑,用环境变量存储连接字符串:

import io
import os
import logging
import pandas as pd
import azure.functions as func
from azure.storage.blob import BlobClient

app = func.FunctionApp()

@app.blob_trigger(arg_name="myblob", path="{containerName}/{name}.xlsb",
                  connection="BlobStorageConnectionString") 
def blob_trigger(myblob: func.InputStream, containerName: str):
    logging.info(f"处理Blob: 名称={myblob.name}, 大小={myblob.length}字节")

    # 提取Blob文件名并替换后缀为xlsx
    blob_name = myblob.name.split("/")[-1]
    output_blob_name = blob_name.replace(".xlsb", ".xlsx")

    # 初始化输出Blob客户端,用环境变量读取连接字符串
    blob_client = BlobClient.from_connection_string(
        conn_str=os.getenv("BlobStorageConnectionString"),
        container_name=containerName,
        blob_name=output_blob_name
    )

    # 直接从触发器输入流读取并解析xlsb文件
    df = pd.read_excel(myblob.read(), engine="pyxlsb")

    # 将DataFrame写入内存流,无需临时文件
    output_stream = io.BytesIO()
    df.to_excel(output_stream, index=False)
    output_stream.seek(0)  # 重置流指针到起始位置

    # 上传转换后的xlsx文件到Blob容器
    blob_client.upload_blob(output_stream, overwrite=True)
    logging.info(f"转换完成,已上传文件: {output_blob_name}")
注意事项
  • 在Azure Function应用的配置-环境变量中添加BlobStorageConnectionString,不要硬编码账户名和密钥,避免泄露。
  • 确保requirements.txt中包含依赖包:
    pandas>=2.0.0
    pyxlsb>=1.0.10
    azure-functions>=1.17.0
    azure-storage-blob>=12.19.0
    
  • Linux环境的/tmp目录有大小限制(默认5GB),超大文件建议分片处理或继续优化内存使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:24:57