我的前端应用程序(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,以(现在)允许所有来源,所有方法和所有标头。
我想念什么?
答案 0 :(得分:0)
包含SAS令牌的查询字符串在URL中编码特殊字符。
因此,您需要在URL上使用decodeURI()
。
答案 1 :(得分:0)
最后,我不太确定是什么解决了这个问题。根据Alex的建议,我首先尝试通过encodeURI()运行URL,但未能解决问题。然后,我尝试使用了decodeURI(),它似乎确实解决了该问题。但是,成功之后,我删除了encodeURI()只是为了仔细检查,它仍然有效。
因此,我不确定这是不是需要一段时间才能生效的CORS设置,我现在所获得的SAS令牌的一些不同之处(与时间有关?),或者只是我忽略了的一些愚蠢的东西。不过,它现在可以正常工作,如果问题再次发生,我将再次尝试解码URI()。