如何在Angular中从ASP.NET Core API下载foo.txt文件
解决Angular中无法接收文件流并实现下载的问题
核心问题
Angular HTTP请求默认响应类型为JSON,后端返回的是文件流(Blob),若不指定响应类型会导致解析失败,无法进入成功回调;同时当前前端请求未传入后端要求的file参数,也会影响请求有效性。
步骤1:修正Angular服务层的请求配置
修改contractAttachementsService中的downloadFile方法,指定响应类型为blob,并传入file参数:
import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class ContractAttachementsService { constructor(private http: HttpClient) {} downloadFile(file: string) { // 替换为你的实际API基础路径 return this.http.get(`/api/download/contractAttachment/${file}`, { responseType: 'blob' // 关键:明确指定响应类型为Blob }); } }
步骤2:实现组件中的文件下载逻辑
在组件的download方法中,接收Blob后通过创建临时DOM元素触发浏览器下载:
download(file: string) { this.contractAttachementsService.downloadFile(file).subscribe(blob => { // 创建Blob临时URL const blobUrl = window.URL.createObjectURL(blob); // 创建隐藏的a标签 const downloadLink = document.createElement('a'); downloadLink.href = blobUrl; // 设置下载文件名(可手动指定,或从后端响应头获取) downloadLink.download = 'foo.txt'; // 触发点击下载 document.body.appendChild(downloadLink); downloadLink.click(); // 清理资源 window.URL.revokeObjectURL(blobUrl); document.body.removeChild(downloadLink); }, error => { console.log(error); }); }
可选优化:从后端响应头动态获取文件名
如果需要后端返回动态文件名,可修改ASP.NET Core后端代码添加响应头:
// GET api/download/contractAttachment [HttpGet("download/{file}")] public IActionResult GetFileAsync(string file) { var fileContent = Encoding.ASCII.GetBytes("foo"); var result = File(fileContent, "text/plain", "foo.txt"); // 添加响应头传递文件名 Response.Headers.Add("Content-Disposition", $"attachment; filename=\"foo.txt\""); return result; }
同时需在ASP.NET Core的CORS配置中暴露该响应头,允许前端读取:
// 在Program.cs/Startup.cs中配置CORS builder.Services.AddCors(options => { options.AddPolicy("AllowDownload", policy => { policy.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader() .WithExposedHeaders("Content-Disposition"); // 暴露自定义响应头 }); }); app.UseCors("AllowDownload");
前端修改为从响应头提取文件名:
download(file: string) { this.contractAttachementsService.downloadFile(file).subscribe({ next: (blob) => { const blobUrl = window.URL.createObjectURL(blob); const downloadLink = document.createElement('a'); downloadLink.href = blobUrl; // 从响应头解析文件名 const contentDisposition = this.httpResponse.headers.get('Content-Disposition'); let filename = 'default.txt'; if (contentDisposition) { const match = contentDisposition.match(/filename="?([^"]+)"?/); if (match?.length > 1) filename = match[1]; } downloadLink.download = filename; document.body.appendChild(downloadLink); downloadLink.click(); window.URL.revokeObjectURL(blobUrl); document.body.removeChild(downloadLink); }, error: (err) => console.log(err) }); }
内容的提问来源于stack exchange,提问作者J.C
相关产品推荐
相关产品推荐

