Angular 14通过HttpPost上传大文件时触发未知错误
Angular 14大文件上传中断(错误码0)解决方案
Angular 14搭建响应式文件上传表单,后端为ASP.NET Core。上传10MB以上大文件时,HttpPost请求10秒左右中途中断,返回错误码0的未知错误;小文件上传正常。Postman上传相同大文件可正常完成,后端未设置文件大小限制,已配置
AllowAnyOrigin()排除CORS问题。
可能的解决方法
1. 延长HTTP请求超时时间
Angular HttpClient默认超时较短,大文件上传需要更长时间,可通过两种方式配置:
单个请求设置超时
在请求中添加timeout操作符:
import { timeout } from 'rxjs/operators'; uploadFile = (files: any) => { if (files.length === 0) { return; } let fileToUpload = <File>files[0]; const formData = new FormData(); formData.append('file', fileToUpload, fileToUpload.name); this.http.post('https://localhost:44468/api/upload', formData, { reportProgress: true, observe: 'events' }) .pipe(timeout(60000)) // 设置60秒超时,可根据文件大小调整 .subscribe({ next: (event: any) => { if (event.type === HttpEventType.UploadProgress) this.progress = Math.round(100 * event.loaded / event.total); else if (event.type === HttpEventType.Response) { this.message = 'Upload success.'; this.onUploadFinished.emit(event.body); } }, error: (err: HttpErrorResponse) => console.log(err) }); }
全局配置超时(推荐)
创建HTTP拦截器统一设置超时:
// timeout.interceptor.ts import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; import { timeout } from 'rxjs/operators'; @Injectable() export class TimeoutInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return next.handle(req).pipe(timeout(60000)); // 全局60秒超时 } }
在AppModule中注册拦截器:
// app.module.ts import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { TimeoutInterceptor } from './timeout.interceptor'; @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true } ] }) export class AppModule { }
2. 分块上传大文件
对于超大文件,分块上传可避免单个请求超时,同时提升上传可靠性:
uploadFile(files: any) { if (files.length === 0) return; const file = files[0]; const chunkSize = 1 * 1024 * 1024; // 1MB每块 const totalChunks = Math.ceil(file.size / chunkSize); const uploadChunk = (index: number) => { const start = index * chunkSize; const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end); const formData = new FormData(); formData.append('file', chunk, file.name); formData.append('chunkIndex', index.toString()); formData.append('totalChunks', totalChunks.toString()); this.http.post('https://localhost:44468/api/upload/chunk', formData) .subscribe({ next: () => { if (index === totalChunks - 1) { // 所有块上传完成,请求服务器合并文件 this.http.post('https://localhost:44468/api/upload/merge', { fileName: file.name }) .subscribe(() => { this.message = '上传成功'; this.onUploadFinished.emit(); }); } else { uploadChunk(index + 1); // 递归上传下一块 } }, error: (err) => { console.error(`第${index+1}块上传失败`, err); // 可添加重试逻辑 } }); }; uploadChunk(0); // 开始上传第一块 }
注:后端需实现分块接收与文件合并的对应接口
3. 排除浏览器环境干扰
- 尝试在浏览器隐身模式下测试,排除扩展插件(如广告拦截器、安全工具)的干扰
- 检查是否使用了代理服务器,尝试直接连接后端测试
内容的提问来源于stack exchange,提问作者Swrena
相关产品推荐
相关产品推荐

