Getting the server response after xhr.send() in an

2019-05-16 09:43发布

I implemented a method to POST a file in my Angular 2 app. It is based on the solution I found here.

Because Angular 2 doesn't support file uploads by itself, the solution has to leverage xhr. This is what the working solution looks like:

The component method:

onSubmit(): void {
    this.inputModuleService.postFile(this.files).subscribe(() => {
        console.log('sent');
    });
}

The service method:

postFile (files: File[]): Observable<string> {
    var url = this.uploadURL;

    return Observable.create(observer => {
        var formData: FormData = new FormData()
        var xhr: XMLHttpRequest = new XMLHttpRequest();

        formData.append("upload", files[i], files[i].name);

        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                    observer.next(JSON.parse(xhr.response));
                    observer.complete();
                } else {
                observer.error(xhr.response);
                }
            }
        };

        xhr.open('POST', url, true);
        xhr.send(formData);
    });
}

My issue is that I don't understand how to get the response back to the onSubmit() method after the call to xhr.send(). Angular2 and the concept of observables and promises are all new to me.

How can I get the server's response from this observable?

1条回答
狗以群分
2楼-- · 2019-05-16 10:22

The server response is provided to the success and error callbacks of subscribe():

onSubmit(): void {
    this.inputModuleService.postFile(this.files).subscribe(
      response => {
          //response is the server's response, parsed into a javascript object
          console.log('server responded: ', response);
      },
      error => {
          //server response emitted when xhr.status !== 200
          console.error(error);
      }
   );
}

This line:

formData.append("upload", files[i], files[i].name);

Will throw errors because i is undefined. The code you copied from had that line within a loop and i was the current index. That's not the case in your code.

Your function declaration:

postFile (files: File[]): Observable<string>

Should be changed to

postFile (files: File[]): Observable<any>

Because the Observable returned by postFile emits objects, not strings.

If you mean to upload just one file, you should also change files: File[] to file: File and append the file with:

formData.append("upload", file, file.name);
查看更多
登录 后发表回答