Slater Slater - 5 months ago 2977
AngularJS Question

File Upload with Angular2 to Rest API

Actually I'm working on a Spring API REST with an interface coded on angular 2.

My problem : CAN'T upload file with angular 2.

My Webresources in java is that :

@RequestMapping(method = RequestMethod.POST, value = "/upload")
public String handleFileUpload(@RequestParam MultipartFile file) {
//Dosomething
}


And it is perfectly working when i call it throught URL request with Auth header etc ....
( with Advanced Rest Client extension for chrome )

proof : http://snag.gy/HbfKN.jpg (everything work fine in that case )

I added the

<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />


In my Srping config file and the Pom dependency

<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2</version>
</dependency>


BUT when i try to do the same thing with a webform :

<input type="file" #files (change)="change(files)"/>
<pre>{{fileContents$|async}}</pre>


With the (change) method :

change(file) {
let formData = new FormData();
formData.append("file", file);
console.log(formData);
let headers = new Headers({
'Authorization': 'Bearer ' + this.token,
'Content-Type': 'multipart/form-data'
});
this.http.post(this.url, formData, {headers}).map(res => res.json()).subscribe((data) => console.log(data));
/*
Observable.fromPromise(fetch(this.url,
{method: 'post', body: formData},
{headers: this.headers}
)).subscribe(()=>console.log('done'));
*/
}


My web service return me an error 500, with that in tomcat logs : http://pastebin.com/PGdcFUQb

I tried the 'Content-Type': undefined method too but without success ( the webservice return me a 415 error in that case.

Can someone help me to figure out what's the problem is ?

problem solved, i'll update that question later with my code :) but, have a look on the plunker it's working perfectly well ( thanks Thierry Templier ! ) ! :)

Answer

In fact, at the moment, you can only provide string input for post, put and patch methods of the Angular2 HTTP support.

To support that, you need to leverage the XHR object directly, as described below:

import {Injectable} from 'angular2/core';
import {Observable} from 'rxjs/Rx';

@Injectable()
export class UploadService {
  constructor () {
    this.progress$ = Observable.create(observer => {
      this.progressObserver = observer
    }).share();
  }

  private makeFileRequest (url: string, params: string[], files: File[]): Observable {
    return Observable.create(observer => {
      let formData: FormData = new FormData(),
        xhr: XMLHttpRequest = new XMLHttpRequest();

      for (let i = 0; i < files.length; i++) {
        formData.append("uploads[]", 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.upload.onprogress = (event) => {
        this.progress = Math.round(event.loaded / event.total * 100);

        this.progressObserver.next(this.progress);
      };

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

See this plunkr for more details: https://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=info.

There is a an issue and a pending PR regarding this in the Angular repo:

Comments