Javascript Angular 5/6:处理从ASP.NET核心API HTTP下载的文件(带友好的文件名)
我目前有一个ASP.NET Core 2.1 API端点,用户可以点击该端点下载CSV文件:Javascript Angular 5/6:处理从ASP.NET核心API HTTP下载的文件(带友好的文件名),javascript,c#,angular,typescript,asp.net-core,Javascript,C#,Angular,Typescript,Asp.net Core,我目前有一个ASP.NET Core 2.1 API端点,用户可以点击该端点下载CSV文件: [HttpPost("Gimme")] public IActionResult Gimme([FromBody] MyOptions options) { MemoryStream reportStream = _reportGenerator.GenerateReportStream(options.StartDate, options.EndDate); return new F
[HttpPost("Gimme")]
public IActionResult Gimme([FromBody] MyOptions options)
{
MemoryStream reportStream = _reportGenerator.GenerateReportStream(options.StartDate, options.EndDate);
return new FileStreamResult(reportStream, "text/csv") { FileDownloadName = "report.csv" };
}
我可以通过邮递员测试它,它返回一个带有正确数据的CSV,没有问题
输入角度。我们与API交互的web站点使用角度驱动的单页应用程序。我已经搜索了各种方法来处理来自API端点的文件,很多方法似乎都是围绕着获取一个Blob和创建一个内联URL,然后通过JavaScript中的window.open()
导航到该URL。或者在内存中创建a
标记,然后调用单击()
我的问题:最新的Angular真的没有办法开箱即用吗?我不是一个角度专家,但我认为应该有一个例子,或者一些内置的机制,将下载的文件提供给浏览器。然而,似乎有很多黑客参与其中
我当前的WIP解决方案确实会将文件返回到浏览器进行下载,但不管API中指定的文件名如何,都会将其作为临时文件名(某些看起来像GUID的东西)下载:
下面是我的组件类和服务类中的内容。我更新了downloadFile()
方法,以使用中提供的答案使友好的文件名正常工作,但我还是希望找到一个不那么麻烦的解决方案
// Component
DownloadReport(options: ReportOptions) {
this._service.getCSV(options).subscribe(data => this.downloadFile(data));
}
downloadFile(blob: Blob) {
const fileName = 'report.csv';
if (navigator.msSaveBlob) {
// IE 10+
navigator.msSaveBlob(blob, fileName);
} else {
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', fileName);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
}
}
// Service
getCSV(reportOptions: ReportOptions): Observable<any> {
let headers = new HttpHeaders();
headers = headers.set('Accept', 'text/csv');
return this._httpClient
.post(`${this.apiRoot}/Gimme`, reportOptions, { headers: headers, responseType: 'blob' })
.catch(this.handleError);
}
//组件
下载报告(选项:报告选项){
this._service.getCSV(options).subscribe(数据=>this.downloadFile(数据));
}
下载文件(blob:blob){
常量文件名='report.csv';
if(navigator.msSaveBlob){
//IE 10+
msSaveBlob(blob,文件名);
}否则{
const link=document.createElement('a');
const url=url.createObjectURL(blob);
link.setAttribute('href',url);
link.setAttribute('下载',文件名);
link.style.visibility='hidden';
document.body.appendChild(链接);
link.click();
document.body.removeChild(link);
revokeObjectURL(URL);
}
}
//服务
getCSV(reportOptions:reportOptions):可观察的解决方案)。有更好的办法吗?一种“最佳实践”的方式?这就是我使用的方式。它基本上和你正在使用的是一样的东西,但在我看来,用锚输入看起来更干净一些。我花了很长时间研究了正确的方法,却找不到一种非黑客的方法
download(): void {
this.service.getFile({ id: id, name: name })
.subscribe(data => {
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
//save file for IE
window.navigator.msSaveOrOpenBlob(data, name);
} else {
const objectUrl: string = URL.createObjectURL(data);
const a: HTMLAnchorElement = document.createElement('a') as HTMLAnchorElement;
a.href = objectUrl;
a.download = name;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(objectUrl);
}
});
}
我认为没有现成的解决方案。使用createObjectURL
,查看这是否有助于创建用户友好的文件名:@David谢谢!我现在使用它来生成名称。还是要把这个问题留给大家,看看是否有一些模糊的角度-y的方法来做到这一点。