HttpRequest 和 reportProgress 不起作用或弄乱了我的请求

HttpRequest and reportProgress not working or messing up my requests

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

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

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

然后我将上传 (post) 调用传递给它,{ 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,我现在真的有点疑惑。

所以举一个明确的例子,现在我收到了对这两个 HttpRequests 的相同响应:

{  
  "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 ... }
}

这个方法可能有帮助

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

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

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

This method [HttpClient.request()] can be called in one of two ways. Either an HttpRequest instance can be passed directly as the only parameter, or a method can be passed as the first parameter, a string URL as the second, and an options hash as the third.

If a HttpRequest object is passed directly, an Observable of the raw HttpEvent stream will be returned.

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

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

return this.http.request('POST', api_enpoint , { body: body, headers: headers, reportProgress: true, withCredentials: true }).map(httpResponse => {
   console.log(httpResponse);
});

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

阅读 后,我添加了 observe: 'events' 参数并开始在我的订阅中接收 HttpEvents。

与 {reportProgress: true} 一起,您需要发送 {observe: 'events'}

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

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

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

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

如果您使用的是 Service Worker,则必须发送 ngsw-bypass header。

示例:-

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

        });
  }