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

2019-05-16 10:34发布

问题:

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:

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