无法生成Azure虚拟目录中已存在的文件的下载链接,使用Spring Boot。

huangapple go评论78阅读模式
英文:

Cant generate a download link for a file that exists in virtual directory in azure using spring boot

问题

我有一个容器,其中包含许多虚拟目录,例如:
https://accountName.blob.core.windows.net/containerName/blobName,而 blob 名称是 Azure 上的虚拟目录,比如:number/name/UUID/anotherUUID/file.txt,我尝试下载 file.txt,但每次都会出现以下错误:
<Code>BlobNotFound</Code>
尽管我可以从 Azure 门户使用 SAS 令牌生成下载链接并成功下载文件,但当我从我的 Spring Boot 应用程序内部生成下载链接时,会出现上述错误。

这是上传 blob 的代码:

BlobClient blob = container.getBlobClient(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("&quot;?&quot;");
String last = stringBuilder.toString();
String result = java.net.URLDecoder.decode(last, StandardCharsets.UTF_8.name());

return result+sasToken;

注意:代码部分不进行翻译。

英文:

i have a container which consists of many virtual directories for example :
https://accountName.blob.core.windows.net/containerName/blobName , and the blob name is a virtual directory on azure let's say for example : number/name/UUID/anotherUUID/file.txt and iam trying to download the file.txt but each time i get the following error :
<Code>BlobNotFound</Code>
although i can generate the download link using sas token from azure portal and get a download link for the file and it is downloaded succesfully , but when i generate the download link from inside my spring boot application i get the error above .

here is the code for uploading a blob :

    BlobClient blob = container.getBlobClient(filePath); // where file path is the virutal directory path
     blob.upload(BinaryData.fromBytes(bytes));

and here is the code for downloading the blob :

 BlobClient blobClient = blobServiceClient.getBlobContainerClient(container name)
          .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(&quot;?&quot;);
      String last = stringBuilder.toString();
      String result = java.net.URLDecoder.decode(last, StandardCharsets.UTF_8.name());

      return result+sasToken;

答案1

得分: 1

我已经在我的环境中使用下面的代码重现了您的要求,并得到了预期的结果。请检查它是否有助于解决问题并满足您的需求。

  • 确保您的容器具有所需的特权

在这里,我使用了POST映射来通过REST API调用上传文件。

@PostMapping("/upload")
public String uploadFile(@RequestParam(value = "file") MultipartFile file) throws IOException {

    String str = "DefaultEndpointsProtocol=https;AccountName=<your_account_name>;AccountKey=<your_account_key>;EndpointSuffix=core.windows.net";

    OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1);
    BlobSasPermission permission = new BlobSasPermission().setReadPermission(true);
    BlobServiceSasSignatureValues values = new BlobServiceSasSignatureValues(expiryTime, permission)
            .setStartTime(OffsetDateTime.now());
    BlobContainerClient container = new BlobContainerClientBuilder().connectionString(str)
            .containerName("<your_container_name>").buildClient();

    BlobClient blob = container.getBlobClient("ParentDir/"+"ChildDir/"+file.getOriginalFilename());
    blob.upload(file.getInputStream(), file.getSize(), true);
    String sasToken = blob.generateSas(values);

    String result = java.net.URLDecoder.decode(blob.getBlobUrl() + "?", StandardCharsets.UTF_8.name());

    return result + sasToken;
}

更新:

在调用BlobClient类时,如果我们将文件名作为参数传递给container.getBlobClient(),它将在容器内创建文件。要在目录内创建文件,我们必须在container.getBlobClient()中传递带有/的目录和文件名,如下所示:

BlobClient blob = container.getBlobClient("ParentDir/"+"ChildDir/"+file.getOriginalFilename());

无法生成Azure虚拟目录中已存在的文件的下载链接,使用Spring Boot。

无法生成Azure虚拟目录中已存在的文件的下载链接,使用Spring Boot。

更新后的输出:

我可以使用生成的URL下载文件,如下所示:

无法生成Azure虚拟目录中已存在的文件的下载链接,使用Spring Boot。

英文:

I have reproduced your requirement in my environment using below code and got expected results. Check if it helps you to fix the issue and achieve your requirement.

  • Be sure that your container has the required privileges.

Here, I'm using the post mapping to upload the file via REST API call.

@PostMapping(&quot;/upload&quot;)
	public String uploadFile(@RequestParam(value = &quot;file&quot;) MultipartFile file) throws IOException {

		String str = &quot;DefaultEndpointsProtocol=https;AccountName=&lt;your_account_name&gt;;AccountKey=&lt;your_account_key&gt;;EndpointSuffix=core.windows.net&quot;;

		OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1);
		BlobSasPermission permission = new BlobSasPermission().setReadPermission(true);
		BlobServiceSasSignatureValues values = new BlobServiceSasSignatureValues(expiryTime, permission)
				.setStartTime(OffsetDateTime.now());
		BlobContainerClient container = new BlobContainerClientBuilder().connectionString(str)
				.containerName(&quot;&lt;your_container_name&gt;&quot;).buildClient();

		BlobClient blob = container.getBlobClient(&quot;ParentDir/&quot;+&quot;ChildDir/&quot;+file.getOriginalFilename());
		blob.upload(file.getInputStream(), file.getSize(), true);
		String sasToken = blob.generateSas(values);

		String  result  = java.net.URLDecoder.decode(blob.getBlobUrl()  +  &quot;?&quot;,  StandardCharsets.UTF_8.name());

     return result +  sasToken;
}

Update:

when calling the BlobClient class, if we pass the filename as parameter in the container.getBlobClient(), it will create file inside the container.
To create file inside the directory, we have to pass directory with / along with the filename inside the container.getBlobClient() as shown below:

BlobClient blob = container.getBlobClient(&quot;ParentDir/&quot;+&quot;ChildDir/&quot;+file.getOriginalFilename());

无法生成Azure虚拟目录中已存在的文件的下载链接,使用Spring Boot。

无法生成Azure虚拟目录中已存在的文件的下载链接,使用Spring Boot。

Updated Output:

I could download the file with the generated URL as shown below:

无法生成Azure虚拟目录中已存在的文件的下载链接,使用Spring Boot。

huangapple
  • 本文由 发表于 2023年3月12日 17:25:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/75712170.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定