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

Spring Boot生成Azure虚拟目录Blob下载链接报BlobNotFound错误

Azure Blob 虚拟目录文件下载报 BlobNotFound 问题

我在Azure存储容器中存放了带虚拟目录结构的Blob,示例Blob路径为https://accountName.blob.core.windows.net/containerName/blobName,其中Blob名称采用虚拟目录格式,比如number/name/UUID/anotherUUID/file.txt。通过Spring Boot应用生成SAS链接下载file.txt时,始终收到<Code>BlobNotFound</Code>错误,但使用Azure门户生成的SAS链接却能正常下载文件。

上传Blob代码

BlobClient blob = container.getBlobClient(filePath); // filePath为虚拟目录路径
blob.upload(BinaryData.fromBytes(bytes));

原下载Blob代码

BlobClient blobClient = blobServiceClient.getBlobContainerClient(containerName)
          .getBlobClient(filePath);

OffsetDateTime expiryTime = OffsetDateTime.now()
                                          .plusDays(1);
BlobSasPermission permission = new BlobSasPermission().setReadPermission(true);
BlobServiceSasSignatureValues values = new BlobServiceSasSignatureValues(expiryTime, permission).setStartTime(
    OffsetDateTime.now());
String sasToken = blobClient.generateSas(values);

String fileUrl = blobClient.getBlobUrl();
StringBuilder stringBuilder = new StringBuilder(fileUrl);
stringBuilder.append("?");
String last = stringBuilder.toString();
String result = java.net.URLDecoder.decode(last, StandardCharsets.UTF_8.name());

return result+sasToken;

问题原因及修复方案

1. 冗余URL解码破坏路径

原代码中对Blob URL执行了不必要的URLDecoder.decode操作:

String result = java.net.URLDecoder.decode(last, StandardCharsets.UTF_8.name());

Azure Blob的虚拟目录斜杠是原生路径分隔符,无需解码。该操作会破坏正确的路径结构,导致生成的URL指向不存在的Blob。

2. SAS令牌拼接重复添加问号

generateSas方法返回的SAS令牌本身已包含?前缀(例如?sv=2023-11-03&ss=b...),原代码手动添加问号会导致URL格式错误,服务器无法正确解析SAS参数,进而触发BlobNotFound错误。

修复后的下载代码

BlobClient blobClient = blobServiceClient.getBlobContainerClient(containerName)
        .getBlobClient(filePath);

OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1);
BlobSasPermission permission = new BlobSasPermission().setReadPermission(true);
BlobServiceSasSignatureValues values = new BlobServiceSasSignatureValues(expiryTime, permission)
        .setStartTime(OffsetDateTime.now());
String sasToken = blobClient.generateSas(values);

// 直接拼接Blob URL与SAS令牌,无需额外处理
return blobClient.getBlobUrl() + sasToken;

额外验证项

  • 确认上传和下载时的filePath参数完全一致(Azure Blob存储对路径大小写敏感)
  • 检查容器名称拼写及大小写是否正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 23:40:03