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

Azure Blob存储Blob项SAS访问令牌生成及读写问题排查

问题:Azure Blob存储Word文件的读写SAS令牌生成及代码故障排查

我是Azure平台新手,需要为Azure Blob存储中的Word文件生成带读写权限的SAS访问令牌。业务场景是用户提交数据后,我接收数据转成字符串数组,写入Blob里的表单文件。已经实现表单更新逻辑,但SAS生成和Blob读写代码无法正常运行,相关代码如下:

async static Task<Uri> GetUserDelegationSasBlob(BlobClient blobClient)
{
    BlobServiceClient blobServiceClient =
        blobClient.GetParentBlobContainerClient().GetParentBlobServiceClient();

    // 获取用户委托密钥 
    Azure.Storage.Blobs.Models.UserDelegationKey userDelegationKey =
        await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                          DateTimeOffset.UtcNow.AddDays(7));

    // 创建SAS令牌
    BlobSasBuilder sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = blobClient.BlobContainerName,
        BlobName = blobClient.Name,
        Resource = "b",
        StartsOn = DateTimeOffset.UtcNow,
        ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
    };

    // 指定SAS的读写权限
    sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write);

    // 为Blob URI添加SAS令牌
    BlobUriBuilder blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
    {
        Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
                                              blobServiceClient.AccountName)
    };

    Console.WriteLine("Blob用户委托SAS URI: {0}", blobUriBuilder);
    Console.WriteLine();
    return blobUriBuilder.ToUri();
}

static async Task ReadBlobWithSasAsync(Uri sasUri)
{
    // 读取文件内容
    public static void Run(Stream myBlob, string fileContent)
    {
        StreamReader contentReader = new StreamReader(myBlob);
        string sampleContent = contentReader.ReadToEnd();
        char[] spearator = { ' ' };
        string[] content = sampleContent.Split(spearator);
        reader.FillForm(content);
    }

    // 创建Blob客户端用于操作
    BlobClient blobClient = new BlobClient(sasUri, null);

    // 下载并读取Blob内容
    try
    {
        Console.WriteLine("Blob内容:");

        // 下载Blob内容到流并读取
        BlobDownloadInfo blobDownloadInfo = await blobClient.DownloadAsync();
        using (StreamReader reader = new StreamReader(blobDownloadInfo.Content, true))
        {
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Console.WriteLine(line);
            }
        }

        Console.WriteLine();
        Console.WriteLine("SAS {0} 读取操作成功", sasUri);
        Console.WriteLine();
    }
    catch (RequestFailedException e)
    {
        // 检查403(禁止访问)错误,SAS无效时Azure Storage会返回该错误
        if (e.Status == 403)
        {
            Console.WriteLine("SAS {0} 读取操作失败", sasUri);
            Console.WriteLine("额外错误信息: " + e.Message);
            Console.WriteLine();
        }
        else
        {
            Console.WriteLine(e.Message);
            Console.ReadLine();
            throw;
        }
    }
}

代码问题分析

  • 语法错误:ReadBlobWithSasAsync方法内部嵌套了Run方法,C#不允许方法嵌套,直接导致编译失败。需将Run方法移到外部或整合逻辑。
  • Word文件解析错误:用StreamReader直接读取.docx文件(二进制格式)会得到乱码,无法正确解析成字符串数组,需用专门的Office文档处理库。
  • 权限风险:使用用户委托SAS需当前身份具备Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action权限,权限不足会导致密钥获取失败,生成无效SAS。
  • 逻辑冗余:ReadBlobWithSasAsync同时包含Blob下载和独立的流读取逻辑,结构混乱,需合并或拆分。

修正后的代码示例

1. 正确生成用户委托SAS的方法

async static Task<Uri> GetUserDelegationSasBlob(BlobClient blobClient)
{
    BlobServiceClient blobServiceClient =
        blobClient.GetParentBlobContainerClient().GetParentBlobServiceClient();

    // 获取用户委托密钥(有效期7天)
    UserDelegationKey userDelegationKey =
        await blobServiceClient.GetUserDelegationKeyAsync(DateTimeOffset.UtcNow,
                                                          DateTimeOffset.UtcNow.AddDays(7));

    // 构建SAS令牌
    BlobSasBuilder sasBuilder = new BlobSasBuilder()
    {
        BlobContainerName = blobClient.BlobContainerName,
        BlobName = blobClient.Name,
        Resource = "b", // 指定为Blob资源
        StartsOn = DateTimeOffset.UtcNow,
        ExpiresOn = DateTimeOffset.UtcNow.AddDays(7)
    };

    // 设置读写权限
    sasBuilder.SetPermissions(BlobSasPermissions.Read | BlobSasPermissions.Write);

    // 生成带SAS的Blob URI
    BlobUriBuilder blobUriBuilder = new BlobUriBuilder(blobClient.Uri)
    {
        Sas = sasBuilder.ToSasQueryParameters(userDelegationKey,
                                              blobServiceClient.AccountName)
    };

    Console.WriteLine("Blob用户委托SAS URI: {0}", blobUriBuilder);
    return blobUriBuilder.ToUri();
}

2. 修正后的Word文件读取处理方法

需先安装DocumentFormat.OpenXml NuGet包用于解析.docx文件:

using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

static async Task ProcessWordBlobWithSasAsync(Uri sasUri)
{
    BlobClient blobClient = new BlobClient(sasUri);

    try
    {
        // 下载Blob到内存流
        BlobDownloadInfo downloadInfo = await blobClient.DownloadAsync();
        using (MemoryStream ms = new MemoryStream())
        {
            await downloadInfo.Content.CopyToAsync(ms);
            ms.Position = 0;

            // 解析Word文档内容
            using (WordprocessingDocument doc = WordprocessingDocument.Open(ms, false))
            {
                Body body = doc.MainDocumentPart.Document.Body;
                string textContent = body.InnerText;
                char[] separator = { ' ' };
                string[] contentArray = textContent.Split(separator);
                
                // 调用表单更新逻辑
                // reader.FillForm(contentArray);
                Console.WriteLine("解析后的字符串数组长度: {0}", contentArray.Length);
            }
        }

        Console.WriteLine("SAS {0} 读取处理成功", sasUri);
    }
    catch (RequestFailedException e)
    {
        if (e.Status == 403)
        {
            Console.WriteLine("SAS {0} 读取失败,权限不足", sasUri);
            Console.WriteLine("错误信息: " + e.Message);
        }
        else
        {
            Console.WriteLine(e.Message);
            throw;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("文件处理失败: " + ex.Message);
        throw;
    }
}

关键注意事项

  • 权限配置:确保生成SAS的身份(Azure AD用户/服务主体)拥有存储账户的存储Blob数据参与者角色,或自定义包含generateUserDelegationKey权限的角色。
  • Word版本兼容:若处理旧版.doc文件,需使用Aspose.Words等支持二进制Word格式的库。
  • SAS有效期:根据业务需求调整ExpiresOn时间,避免过长有效期带来安全风险。
  • 异常扩展:可增加Blob不存在、文件格式错误等场景的异常捕获,提升代码健壮性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 08:35:02