在 Angular 5 中通过 blob 下载时设置文件名



下面是我的打字稿代码,用于从API下载文件

DownloadLM() {
var ID= sessionStorage.getItem("UserID");
return this.http.get(this.baseurl + 'api/DownloadFiles/DownloadLM/' + ID,
{
headers: {
'Content-Type': 'application/json'
},
responseType: 'arraybuffer'
}
)
.subscribe(respData => {
this.downLoad(respData, this.type);
}, error => {
});
}
downLoad(data: any, type: string) {
var blob = new Blob([data], { type: type.toString() });
var url = window.URL.createObjectURL(blob);
var pwa = window.open(url);
if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
alert('Please disable your Pop-up blocker and try again.');
}
}

下载Excel文件很好,但它为我不想要的文件提供了一个随机名称,我想在下载时设置我选择的文件名,

我在哪里可以在这里设置文件名? Blob 的任何属性?

您可以将下载属性设置为所需的文件名,将 href 设置为对象 url,然后只需调用单击

var blob = new Blob([data], { type: type.toString() });
var url = window.URL.createObjectURL(blob);
var anchor = document.createElement("a");
anchor.download = "myfile.txt";
anchor.href = url;
anchor.click();

如果需要上传文件的确切文件名,请从支持的 API 流中设置文件名的自定义标头。

你可以像这样使用它:我的 Excel API 响应标头:

content-disposition: inline;filename="salesReport.xls" 
content-type: application/octet-stream 
date: Wed, 22 Aug 2018 06:47:28 GMT 
expires: 0 
file-name: salesReport.xls 
pragma: no-cache 
transfer-encoding: chunked 
x-application-context: application:8080 
x-content-type-options: nosniff 
x-xss-protection: 1; mode=block

服务网

excel(data: any) {
return this.httpClient.post(this.config.domain + 
`/api/registration/excel/download`,data, {observe: 'response', responseType: 'blob'})
.map((res) => {
let data = {
image: new Blob([res.body], {type: res.headers.get('Content-Type')}),
filename: res.headers.get('File-Name')
}
return data ;
}).catch((err) => {
return Observable.throw(err);
});
}

组件.ts

excelDownload (data) {
this.registration.excel(data).subscribe(
(res) => {
const element = document.createElement('a');
element.href = URL.createObjectURL(res.image);
element.download = res.filename;
document.body.appendChild(element);
element.click();
this.toastr.success("Excel generated  successfully");
},
(error) =>{
this.toastr.error('Data Not Found');
});
}

由于有些人要求一个有承诺的版本,所以你可以使用 await und async:

第 1 部分:从服务器获取 Blob:

generateSapExcel(data: GenerateSapExport): Promise<HttpResponse<Blob>> {
return this.http.post(`${this.pathprefix}/GenerateSapExcel`, data, { responseType: 'blob', observe: 'response' })
.toPromise()
.catch((error) => this.handleError(error));
}

第 2 部分:提取 HttpResponse 并将其交付给用户:

public downloadFile(data: HttpResponse<Blob>) {
const contentDisposition = data.headers.get('content-disposition');
const filename = this.getFilenameFromContentDisposition(contentDisposition);
const blob = data.body;
const url = window.URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.download = filename;
anchor.href = url;
anchor.click();
}
private getFilenameFromContentDisposition(contentDisposition: string): string {
const regex = /filename=(?<filename>[^,;]+);/g;
const match = regex.exec(contentDisposition);
const filename = match.groups.filename;
return filename;
}

第 3 部分:将两者结合起来:

const blobresponse = await this.dataService.generateSapExcel(dataToSend);
this.downloadService.downloadFile(blobresponse);

第 4 部分:服务器:

[HttpPost]
[Route(nameof(GenerateSapExcel))]
public async Task<FileStreamResult> GenerateSapExcel(GenerateSapExportDto dto)
{
Stream stream = await _sapKurepoService.GenerateSapExcel(dto);
FileStreamResult result = File(stream, FileHelper.ContentypeExcel, "excel.xlsx");
return result;
}

我个人发现在这种情况下使用文件类型而不是 Blob 非常顺利。我能够命名文件,并避免创建必须单击的锚标签。

下面是您更新的 download(( 函数。具有"application/octet-stream"的文件类型对于向window.open((指示URL应该用作下载而不是浏览器显示是必要的。

download(data: any) {
let file = new File([data], 'file.json', { type: 'application/octet-stream' });
let url = window.URL.createObjectURL(file);
var pwa = window.open(url);
if (!pwa || pwa.closed || typeof pwa.closed == 'undefined') {
alert('Please disable your Pop-up blocker and try again.');
}
}

希望这有帮助!

最新更新