Angular2上传视频至MinIO时如何实现进度条显示?
Angular2上传大文件到MinIO无法获取上传进度,订阅返回null
我用Angular2向MinIO上传大视频文件,想显示上传进度条。流程是先调用API的POST请求拿到MinIO直传链接,再用这个链接上传视频,但不管怎么配置,订阅上传请求时始终返回null,进度也拿不到。
获取MinIO直传链接的服务代码
postLecture(lectureData: any): Observable<any> { this.addJwtToHeaders(); const url = `${this.apiUrl}/x_lecture/`; return this.http.post<any>(url, lectureData, httpOptions); }
上传视频到MinIO的服务代码(期望获取进度)
uploadVideoToMinio( url: string, lectureData: any, file: any ): Observable<any> { this.addJwtToHeaders(); let value = lectureData.videos[0].video_format; let video = new FormData(); video.append('video', file); let httpOptions2 = { headers: new HttpHeaders({ 'Content-Type': 'audio/mp4', }), reportProgress: true, options: { observe: 'events', }, }; return this.http.put<any>(url, file, httpOptions2); }
组件调用代码
this.uploadSubs = this.uploadVideoService .postLecture(lectureData) .subscribe( (res: any) => { console.log(res); console.log(res.type); console.log(res.type.DownloadProgress); if (res.videos[0].video_put_url) { let url: string = res.videos[0].video_put_url; this.minioSubs = this.uploadVideoService .uploadVideoToMinio(url, lectureData, this.selectedVideo) .subscribe( (res) => { console.log(res); if (res.type == HttpEventType.UploadProgress) { console.log(Math.round((100 / res.total) * res.loaded)); } console.log(res); console.log(res.type); console.log(res.type.DownloadProgress); }, (error) => { console.log(error); } ); } }, (error) => { console.log(error); } );
相关截图



我还试过其他配置,比如:
let httpOptions2 = { headers: new HttpHeaders({ 'Content-Type': 'audio/mp4', }), reportProgress: true, };
问题根源及修复方案
observe配置层级错误
你把observe: 'events'嵌套在了options属性里,这不符合Angular HTTP配置规则。observe是顶级配置项,只有将其设为'events',才能接包含进度信息的事件流,否则只会返回最终响应体,进度事件根本不会触发。Content-Type配置错误
你错误设置了audio/mp4(应为video/mp4),且直接手动指定Content-Type会导致请求格式异常。如果是直接上传文件二进制,应使用文件自身的MIME类型;如果用FormData上传,无需手动设置Content-Type,浏览器会自动生成带boundary的multipart/form-data头。另外,MinIO直传链接已包含签名信息,不需要额外添加JWT头,否则可能导致签名验证失败。FormData未实际使用
代码中创建了FormData但最终上传的是file本身,导致请求体格式不匹配,需二选一:要么用FormData传递,要么直接传文件二进制。
修改后的服务代码
uploadVideoToMinio( url: string, file: File ): Observable<HttpEvent<any>> { const httpOptions2 = { reportProgress: true, observe: 'events' as const, // 明确类型避免TS报错 headers: new HttpHeaders({ 'Content-Type': file.type || 'video/mp4' }) }; // 直接传文件二进制(MinIO PUT直传默认支持此方式) return this.http.put(url, file, httpOptions2); }
修改后的组件调用代码
this.minioSubs = this.uploadVideoService .uploadVideoToMinio(url, this.selectedVideo) .subscribe( (event) => { if (event.type === HttpEventType.UploadProgress) { const progress = Math.round((100 * event.loaded) / event.total!); console.log(`上传进度:${progress}%`); // 此处将progress绑定到进度条组件即可 } else if (event.type === HttpEventType.Response) { console.log('上传完成'); } }, (error) => { console.error('上传失败', error); } );
额外注意事项
- 确认MinIO直传链接有效性,确保支持PUT请求且签名未过期。
- 若需用FormData上传,需移除手动设置的Content-Type:
const formData = new FormData(); formData.append('video', file); const httpOptions2 = { reportProgress: true, observe: 'events' as const, }; return this.http.put(url, formData, httpOptions2);
内容的提问来源于stack exchange,提问作者devZ
相关产品推荐
相关产品推荐

