Angular - POST uploaded file Angular - POST uploaded file angular angular

Angular - POST uploaded file


Look at my code, but be aware. I use async/await, because latest Chrome beta can read any es6 code, which gets by TypeScript with compilation. So, you must replace asyns/await by .then().

Input change handler:

/** * @param fileInput */public psdTemplateSelectionHandler (fileInput: any){    let FileList: FileList = fileInput.target.files;    for (let i = 0, length = FileList.length; i < length; i++) {        this.psdTemplates.push(FileList.item(i));    }    this.progressBarVisibility = true;}

Submit handler:

public async psdTemplateUploadHandler (): Promise<any> {    let result: any;    if (!this.psdTemplates.length) {        return;    }    this.isSubmitted = true;    this.fileUploadService.getObserver()        .subscribe(progress => {            this.uploadProgress = progress;        });    try {        result = await this.fileUploadService.upload(this.uploadRoute, this.psdTemplates);    } catch (error) {        document.write(error)    }    if (!result['images']) {        return;    }    this.saveUploadedTemplatesData(result['images']);    this.redirectService.redirect(this.redirectRoute);}

FileUploadService. That service also stored uploading progress in progress$ property, and in other places, you can subscribe on it and get new value every 500ms.

import { Component } from 'angular2/core';import { Injectable } from 'angular2/core';import { Observable } from 'rxjs/Observable';import 'rxjs/add/operator/share';@Injectable()export class FileUploadService {/** * @param Observable<number> */private progress$: Observable<number>;/** * @type {number} */private progress: number = 0;private progressObserver: any;constructor () {    this.progress$ = new Observable(observer => {        this.progressObserver = observer    });}/** * @returns {Observable<number>} */public getObserver (): Observable<number> {    return this.progress$;}/** * Upload files through XMLHttpRequest * * @param url * @param files * @returns {Promise<T>} */public upload (url: string, files: File[]): Promise<any> {    return new Promise((resolve, reject) => {        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) {                    resolve(JSON.parse(xhr.response));                } else {                    reject(xhr.response);                }            }        };        FileUploadService.setUploadUpdateInterval(500);        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);    });}/** * Set interval for frequency with which Observable inside Promise will share data with subscribers. * * @param interval */private static setUploadUpdateInterval (interval: number): void {    setInterval(() => {}, interval);}}


Looking onto this issue Github - Request/Upload progress handling via @angular/http, angular2 http does not support file upload yet.

For very basic file upload I created such service function as a workaround (using Тимофей's answer):

  uploadFile(file:File):Promise<MyEntity> {    return new Promise((resolve, reject) => {        let xhr:XMLHttpRequest = new XMLHttpRequest();        xhr.onreadystatechange = () => {            if (xhr.readyState === 4) {                if (xhr.status === 200) {                    resolve(<MyEntity>JSON.parse(xhr.response));                } else {                    reject(xhr.response);                }            }        };        xhr.open('POST', this.getServiceUrl(), true);        let formData = new FormData();        formData.append("file", file, file.name);        xhr.send(formData);    });}


your http service file:

import { Injectable } from "@angular/core";import { ActivatedRoute, Router } from '@angular/router';import { Http, Headers, Response, Request, RequestMethod, URLSearchParams, RequestOptions } from "@angular/http";import {Observable} from 'rxjs/Rx';import { Constants } from './constants';declare var $: any;@Injectable()export class HttpClient {  requestUrl: string;  responseData: any;  handleError: any;  constructor(private router: Router,   private http: Http,   private constants: Constants,   ) {    this.http = http;  }  postWithFile (url: string, postData: any, files: File[]) {    let headers = new Headers();    let formData:FormData = new FormData();    formData.append('files', files[0], files[0].name);    // For multiple files    // for (let i = 0; i < files.length; i++) {    //     formData.append(`files[]`, files[i], files[i].name);    // }    if(postData !=="" && postData !== undefined && postData !==null){      for (var property in postData) {          if (postData.hasOwnProperty(property)) {              formData.append(property, postData[property]);          }      }    }    var returnReponse = new Promise((resolve, reject) => {      this.http.post(this.constants.root_dir + url, formData, {        headers: headers      }).subscribe(          res => {            this.responseData = res.json();            resolve(this.responseData);          },          error => {            this.router.navigate(['/login']);            reject(error);          }      );    });    return returnReponse;  }}

call your function (Component file):

onChange(event) {    let file = event.srcElement.files;    let postData = {field1:"field1", field2:"field2"}; // Put your form data variable. This is only example.    this._service.postWithFile(this.baseUrl + "add-update",postData,file).then(result => {        console.log(result);    });}

your html code:

<input type="file" class="form-control" name="documents" (change)="onChange($event)" [(ngModel)]="stock.documents" #documents="ngModel">