ngsubmit ngform navigationend form angular typescript file-upload angular2-http

navigationend - ngform angular 6



Angular: archivo cargado POST (5)

Estoy usando Angular , TypeScript para enviar un archivo, junto con datos JSON a un servidor.

Abajo está mi código:

import {Component, View, NgFor, FORM_DIRECTIVES, FormBuilder, ControlGroup} from ''angular2/angular2''; import {Http, Response, Headers} from ''http/http''; @Component({ selector: ''file-upload'' }) @View({ directives: [FORM_DIRECTIVES], template: ` <h3>File Upload</h3> <div> Select file: <input type="file" (change)="changeListener($event)"> </div> ` }) export class FileUploadCmp { public file: File; public url: string; headers: Headers; constructor(public http: Http) { console.log(''file upload Initialized''); //set the header as multipart this.headers = new Headers(); this.headers.set(''Content-Type'', ''multipart/form-data''); this.url = ''http://localhost:8080/test''; } //onChange file listener changeListener($event): void { this.postFile($event.target); } //send post file to server postFile(inputValue: any): void { var formData = new FormData(); formData.append("name", "Name"); formData.append("file", inputValue.files[0]); this.http.post(this.url +, formData , { headers: this.headers }); } }

¿Cómo puedo transformar formData a String y enviarlo al servidor? Recuerdo que en AngularJS (v1) usarías transformRequest .


Analizando este problema Github: gestión de progreso de solicitud / carga a través de @ angular / http , angular2 http aún no admite la carga de archivos.

Para la carga de archivos muy básica, creé dicha función de servicio como una solución alternativa (usando la respuesta de Тимофей ):

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


En mi proyecto, uso XMLHttpRequest para enviar datos multiparte / formulario. Creo que te quedará bien.

y el código del uploader

let xhr = new XMLHttpRequest(); xhr.open(''POST'', ''http://www.example.com/rest/api'', true); xhr.withCredentials = true; xhr.send(formData);

Aquí hay un ejemplo: https://github.com/wangzilong/angular2-multipartForm


Mira mi código, pero ten en cuenta. Utilizo async / await, porque la última versión beta de Chrome puede leer cualquier código es6, que obtiene TypeScript con la compilación. Por lo tanto, debe reemplazar asyns / .then() por .then() .

Controlador de cambio de entrada:

/** * @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; }

Enviar manejador:

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. Ese servicio también almacenó cargando progreso en progreso $ propiedad, y en otros lugares, puede suscribirse y obtener un nuevo valor cada 500 ms.

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


Primero, debe crear su propia clase TS en línea, ya que la clase FormData no está bien soportada en este momento:

var data : { name: string; file: File; } = { name: "Name", file: inputValue.files[0] };

Luego lo envía al servidor con JSON.stringify (datos)

let opts: RequestOptions = new RequestOptions(); opts.method = RequestMethods.Post; opts.headers = headers; this.http.post(url,JSON.stringify(data),opts);


su archivo de servicio http:

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

llame a su función (archivo de componente):

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

su código html:

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