如何从Angular使用SAS下载Azure Blob存储blob?

时间:2020-08-14 00:14:44

标签: angular azure azure-blob-storage

我的前端应用程序(Angular 8)需要能够从多个存储提供程序(当前为Azure Blob存储和Autodesk OSS)下载文件。我希望前端直接从提供程序下载,而不必先在后端下载。我想避免让前端关心特定的提供程序,因此,我试图避免在前端使用特定于提供程序的SDK(例如@ azure / storage-blob),而是检索经过预先验证的URL从我的后端,然后从那里下载。

我正在使用以下代码来检索有关文件(URL,文件名和内容类型)的元数据,对检索到的(预先认证的)URL进行GET请求以下载数据,然后使用saveAs(从文件中提取) -saver软件包)保存到磁盘:

  downloadDocument(id: string) {
    this.getDocumentFileInfo(id).pipe(
      concatMap(fileInfo => {
        const headers = new HttpHeaders().set('Accept', fileInfo.contentType);
        return combineLatest(this.http.get(fileInfo.url, { responseType: 'arraybuffer',
          headers: headers }), of(fileInfo));
      })
    )
    .subscribe(latest => {
      const [data, fileInfo] = latest;
      const blob = new Blob([data], { type: fileInfo.contentType });
      saveAs(blob, fileInfo.name);
    });
  }

  private getDocumentFileInfo(id: string): Observable<DocumentFileInfo> {
    return this.http.get<Document>(`${this._config.apiUrl}documents/${id}/fileinfo`, {withCredentials: true}).pipe(
      catchError((error: any) => this.handleError(error))
    );
  }

使用此代码从Azure Blob存储下载时,我收到以下消息的403响应:

服务器无法验证请求。确保包括签名在内的Authorization标头的值正确形成。

如果我复制从浏览器开发工具记录的URL,然后将其粘贴到新选项卡的地址栏中,则文件下载正常,因此SAS似乎没有问题。我还为我的存储帐户设置了CORS,以(现在)允许所有来源,所有方法和所有标头。

我想念什么?

2 个答案:

答案 0 :(得分:0)

包含SAS令牌的查询字符串在URL中编码特殊字符。

因此,您需要在URL上使用decodeURI()

答案 1 :(得分:0)

最后,我不太确定是什么解决了这个问题。根据Alex的建议,我首先尝试通过encodeURI()运行URL,但未能解决问题。然后,我尝试使用了decodeURI(),它似乎确实解决了该问题。但是,成功之后,我删除了encodeURI()只是为了仔细检查,它仍然有效。

因此,我不确定这是不是需要一段时间才能生效的CORS设置,我现在所获得的SAS令牌的一些不同之处(与时间有关?),或者只是我忽略了的一些愚蠢的东西。不过,它现在可以正常工作,如果问题再次发生,我将再次尝试解码URI()。