【问题标题】:HttpRequest and reportProgress not working or messing up my requestsHttpRequest 和 reportProgress 不起作用或弄乱了我的请求
【发布时间】:2018-09-26 08:54:20
【问题描述】:

我正在使用 Angular 5 实现文件上传服务,我想给用户一些关于上传进度的反馈。我发现有几页建议使用 Angulars HttpClient 附带的 reportProgress 参数,但我无法让它工作。

我对所有的 http 请求都使用了一个包装类,然后它会执行一些逻辑,最后所有请求都以被调用的相同方法结束:

public request(request: HttpRequest<any>, options?: any): Observable<any> {
  return this.httpClient.request(request.method, request.url, {
    body: request.body,
    headers: request.headers,
    responseType: request.responseType,
    ...options
  });
}

然后我将一个上传(发布)调用传递给它,{ reportProgress: true }options。这根本不起作用,请求没有任何改变。所以我怀疑,我实际上需要在 HttpRequest 构造函数中使用reportProgress-参数来使其工作并相应地更改我的代码:

public request(request: HttpRequest<any>, options?: any): Observable<any> {
  return this.httpClient.request(
    new HttpRequest(request.method, request.url, request.body, {
      headers: request.headers,
      responseType: request.responseType,
      ...options
    })
  );
}

这导致了更奇怪的行为,现在无论我的选项是什么样的,我总是只收到 {type: 0} 作为请求的响应。

我在监督什么?我使用 Angular 5.1.1,我现在真的有点困惑。

举个明确的例子,现在我收到了这两个 HttpRequest 的相同响应:

{  
  "url":"http://127.0.0.1:8888/test",
  "body":{  
   "data":"testdata"
  },
  "reportProgress":false,
  "withCredentials":false,
  "responseType":"json",
  "method":"POST",
  "headers":{ some-headers ... }
}

这个请求:

{  
  "url":"http://127.0.0.1:8888/api/pages",
  "body":{  
    "pageUrl":"http://localhost:1234/"
  },
  "reportProgress":true,
  "withCredentials":false,
  "responseType":"json",
  "method":"POST",
  "headers":{ some-headers ... }
}

【问题讨论】:

  • 你为什么使用包装类而不是interceptor?另请注意,.clone 方法可能是基于现有请求创建新请求的更好方法。
  • 因为包装器已经写了一段时间了,还没有时间重写它。我知道.clone()-方法,但想要一种通用方法,我不必检查选项对象中的单个属性。

标签: angular file-upload httprequest angular-httpclient


【解决方案1】:

连同 {reportProgress: true} 您需要发送 {observe: '事件'}

this.httpClient.post(environment.uploadDocument, file, { reportProgress: true, observe: 'events' })
.subcribe(data =>{
if (data['type'] === HttpEventType.UploadProgress) {
   console.log('loaded ', data['loaded'], '   total  -', data['total']);
   }
})

【讨论】:

  • observe: "events" 使文件损坏
  • 我一直在使用相同的。对我有用。如果您可以分享有关您的项目的更多详细信息。
【解决方案2】:

这个方法可能有帮助

public progress: number = 0;
public message: string = "";

constructor(private http: HttpClient) {}

onSubmit() {
    // replace with your request data
    const formModel = this.userForm.value;
    let formData = new FormData();

    formData.append("upload", formModel.upload);

    const uploadReq = new HttpRequest('POST', 'api/Upload', formData, {
        reportProgress: true,
    });

    this.http.request(uploadReq).subscribe((event) => {
        if (event.type === HttpEventType.UploadProgress) {
            this.progress = Math.round(100 * event.loaded / event.total);
        }
        else if (event.type === HttpEventType.Response) {
            this.message = event.body.toString();
        }
    });
}

【讨论】:

  • 抱歉,但这只是您在谷歌搜索如何使用 angular 跟踪上传进度时发现的第一个 sn-p(我已经找到:“我发现有几个页面建议使用 reportProgress 参数”)。答案没有对我的实际问题提供任何意见...
  • @newnoise,这是我目前正在使用的,它有效;即使它是 Google 中的第一个结果。
【解决方案3】:

我解决了这些问题。问题中描述的行为实际上涉及两件事。

首先... rtfm! https://angular.io/api/common/http/HttpClient

此方法 [HttpClient.request()] 可以通过以下两种方式之一调用。可以直接将 HttpRequest 实例作为唯一参数传递,也可以将方法作为第一个参数传递,字符串 URL 作为第二个参数,选项哈希作为第三个参数。

如果直接传递 HttpRequest 对象,则会返回原始 HttpEvent 流的 Observable。

这解释了为什么我的两个请求(无论 reportProgress 参数是 true 还是 false,从现在开始都以 HttpRequest 的形式返回 {type: 0}

另一方面,仅接收 SENT 事件 ({type: 0}) 是后端本身的错误配置。

【讨论】:

  • 您能否详细说明您是如何解决该问题的?
  • the documentation可以找到更多细节:"观察值决定返回类型,根据你有兴趣观察什么" 1) 事件的观察值返回原始HttpEvent 流的可观察值,默认情况下包括进度事件。 2) 响应的观察值返回HttpResponse&lt;T&gt; 的可观察值,其中T 参数取决于responseType 和任何可选提供的类型参数。 3) body 的观察值返回 &lt;T&gt; 的 observable,具有相同的 T 正文类型。
  • 后端的错误配置是什么?我们需要在后端进行任何特殊处理吗?
【解决方案4】:

阅读https://stackoverflow.com/a/54899930/1429439 后,我添加了 observe: 'events' 参数并开始在我的订阅中接收 HttpEvents。

【讨论】:

    【解决方案5】:
    return this.http.request('POST', api_enpoint , { body: body, headers: headers, reportProgress: true, withCredentials: true }).map(httpResponse => {
       console.log(httpResponse);
    });
    

    您需要以这种方式传递请求,而不是传递 httpRequest 对象(适用于 http 和 https)

    【讨论】:

      【解决方案6】:

      上传表单数据以及标题详细信息

      此片段将帮助您上传表单数据,并且在订阅时您也可以实现进度条

      uploadMyImage(formData: any) {
          const httpOptions = new HttpHeaders({
            'Content-Type': 'multipart/form-data', 'boundary': 'something'
            });
          return this.http.post('http://localhost:4000/api/upload', formData, { reportProgress: true, observe: 'events', headers: httpOptions });
        }
      

      【讨论】:

        【解决方案7】:

        如果您使用的是 service worker,您必须发送 ngsw-bypass 标头。

        例子:-

        file: File;
        
        uploadProgress: number;
        
        constructor(private http: HttpClient) { }
        
        uploadData(): void {
        
            const formData = new FormData();
            formData.append('file', this.file);
        
        
            const headers = new HttpHeaders({ 'ngsw-bypass': '' });
        
            this.http.post(`upload url`, formData, {
              reportProgress: true,
              observe: 'events',
              headers
            }).subscribe(event => {
        
                    if (event.type === HttpEventType.UploadProgress) {
                        this.uploadProgress = Math.round(100 * event.loaded / event.total);
                    }
                    else if (event.type === HttpEventType.Response) {
                        console.log(event.body);
                    }
        
                });
          }
        

        【讨论】:

          猜你喜欢
          • 2016-09-13
          • 1970-01-01
          • 1970-01-01
          • 2015-04-19
          • 1970-01-01
          • 2015-09-03
          • 1970-01-01
          • 2017-03-01
          • 1970-01-01
          相关资源
          最近更新 更多