Angular中ngFor展示ZIP下载链接时createObjectURL报错求助
Angular生成ZIP下载链接时createObjectURL报错解决方案
问题说明
在Angular应用中实现ZIP文件下载并生成可点击链接,当前代码能完成文件下载打开,但控制台持续报错:
Failed to execute 'createObjectURL' on 'URL': Overload resolution failed
报错触发行:
this.zipFile[0].fileUrl = window.URL.createObjectURL(this.zipFile[0].fileContent);
报错原因
- 响应获取方式错误:服务中使用
observe: "events",订阅返回的是HttpEvent对象流,而非直接的Blob响应体,value.body可能未正确获取到有效Blob; - 类型不匹配:
createObjectURL仅接受Blob/File/MediaSource类型参数,若fileContent不是上述类型(比如为undefined或其他对象),则会触发重载解析失败; - 内存泄漏风险:未及时回收创建的Object URL,长期运行可能导致内存占用过高。
修复方案
1. 调整HTTP请求的观察模式
修改服务代码,将observe改为"body",直接获取Blob响应体:
public downloadFileWithAuthorization(urlOfFile: string, user: string, password: string): Observable<Blob> { const headerParams = new HttpHeaders({ "Content-Type": "application/x-www-form-urlencoded", "Authorization": "Basic " + btoa(user + ":" + password), }); return this.http.get(urlOfFile, { reportProgress: false, observe: "body", // 改为直接获取响应体 headers: headerParams, responseType: "blob" }); }
2. 组件中正确处理Blob并添加类型校验
在组件订阅回调中,确保拿到有效Blob后再创建Object URL,并添加类型检查:
getDownloadFile() { this.downloadFileSub = this.downloadService.downloadFileWithAuthorization( this.emailMessage!.downloadURL![0].path!, this.user, this.password ).subscribe({ next: (blob) => { // 校验是否为有效Blob if (blob instanceof Blob) { this.zipFile[0].fileContent = blob; this.zipFile[0].fileUrl = window.URL.createObjectURL(blob); } }, error: err => { new ErrorMessage(err.message, this.messageService).provide(); } }); } // 组件销毁时释放Object URL,避免内存泄漏 ngOnDestroy() { if (this.zipFile[0]?.fileUrl) { window.URL.revokeObjectURL(this.zipFile[0].fileUrl); } this.downloadFileSub?.unsubscribe(); }
3. 优化HTML链接绑定
使用Angular属性绑定代替插值表达式,避免XSS风险:
<div *ngFor="let urlentity of zipFile"> <button pButton pRipple icon="p-button-icon pi pi-file-edit" link="true" class="p-button-rounded p-button-success mr-2"> <a [href]="urlentity.fileUrl" target="_blank" rel="noopener noreferrer">{{urlentity.name}}</a> </button> </div>
额外说明
若仍需监听下载进度,可保留observe: "events",但需在回调中判断事件类型为HttpResponse时再获取body:
next: (event) => { if (event instanceof HttpResponse && event.body instanceof Blob) { this.zipFile[0].fileContent = event.body; this.zipFile[0].fileUrl = window.URL.createObjectURL(event.body); } }
内容的提问来源于stack exchange,提问作者DigitalMachine
相关产品推荐
相关产品推荐

