我正在尝试从 api url 获取文件。我的目标是在输入文件字段中显示该文件(之前上传的)及其名称。目前我已经创建了以下服务功能:
getDocument(): Observable<Blob> {
const request = this.documentUrl;
return this.http.get(request, { responseType: 'blob' });
}
当我使用它时
this.myService.getDocument().subscribe(
response => {
console.log(response);
}
我得到一个 Blob,根据定义,它没有名称。我已经看到我可以将其转换为文件并为其命名,但此解决方案不符合我的需要。有没有办法可以从后端获取文件,或者有没有办法用 Blob 的原始名称重建它?
请确保后端API在响应头中设置了文件名。通常,文件名包含在
content-disposition
标头中。
例如:看起来像
content-disposition: attachment;filename=XYZ.csv
。
在 Angular 中,您可以像下面这样提取它:
.subscribe((response: HttpResponse<Blob>) => {
// Extract content disposition header
const contentDisposition = response.headers.get('content-disposition');
// Extract the file name
const filename = contentDisposition
.split(';')[1]
.split('filename')[1]
.split('=')[1]
.trim()
.match(/"([^"]+)"/)[1];
});
请确保后端API在响应头中设置了文件名。通常,文件名包含在内容处置标头中。
我发现这要归功于this答案以及thisCORS策略不允许Angular查看所有标头,我使用Java作为后端,这就是我解决问题的方法:
角度:
this.myService.downloadBlob(BlobID).subscribe(
(response: HttpResponse<Blob>) => {
//same code as andsilver
// Extract content disposition header
const contentDisposition = response.headers.get('content-disposition');
// Rest of your code to extract filename using contentDisposition
// Extract the file name
const filename = contentDisposition
.split(';')[1]
.split('filename')[1]
.split('=')[1]
.trim();
this.downloadBlob(new Blob([(response.body)], { type: 'text/plain' }), filename);
}
服务角度:
downloadBlob(BlobID: number): Observable<HttpResponse<Blob>> {
return this.http.get(myUrl+'?BlobID='+BlobID, { observe: 'response', responseType: 'blob' });
}
服务器端(在我的例子中是Java):
@GetMapping("/downloadBlob")
public ResponseEntity<byte[]> downloadBlob(@RequestParam("BlobID") BigDecimal BlobID) {
BlobAndName blobAndName = service.getDocumento(BlobID);
byte[] blobAsBytes = Utils.blob2ByteArray(blobAndName.getBlob());
HttpHeaders head = new HttpHeaders();
head.add("content-disposition", "attachment; filename=" + blobAndName.getName());
ArrayList<String> exposedHead = new ArrayList<>();
exposedHead.add("content-disposition");
head.setAccessControlExposeHeaders(exposedHead);
return ResponseEntity.ok().headers(head).body(blobAsBytes);
}
我必须说,由于我的同事的安全问题(没有向我解释,所以我什至不知道它们是什么),这不是我实现的解决方案,我通过不同的方法获得了名称和 blob因为我有机会通过回收以前的一个来做到这一点,它已经为我提供了我需要的不同信息,现在也为我提供了 blob 名称。