You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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);
    }
  );

相关截图

控制台输出1
控制台输出2
控制台输出3

我还试过其他配置,比如:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 09:10:34