Angular – arquivo carregado por POST

Eu estou usando Angular , TypeScript para enviar um arquivo, juntamente com dados JSON para um servidor.

Abaixo está o meu 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: ` 

File Upload

Select file:
` }) 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 }); } }

Como posso transformar o formData em String e enviá-lo para o servidor? Eu lembro que no AngularJS (v1) você usaria transformRequest .

Olhe meu código, mas esteja ciente. Eu uso async / wait, porque o beta do Chrome mais recente pode ler qualquer código es6, que é obtido com o TypeScript com a compilation. Portanto, você deve replace asyns / await por .then() .

Manipulador de mudança de input:

 /** * @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 manipulador:

 public async psdTemplateUploadHandler (): Promise { 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. Esse serviço também armazena o progresso do upload em andamento, e em outros lugares, você pode se inscrever nele e obter um novo valor a 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 */ private progress$: Observable; /** * @type {number} */ private progress: number = 0; private progressObserver: any; constructor () { this.progress$ = new Observable(observer => { this.progressObserver = observer }); } /** * @returns {Observable} */ public getObserver (): Observable { return this.progress$; } /** * Upload files through XMLHttpRequest * * @param url * @param files * @returns {Promise} */ public upload (url: string, files: File[]): Promise { 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); } } 

Olhando para essa questão Github – Solicitação / Upload de manipulação de progresso via @ angular / http , angular2 http não suporta o upload de arquivos ainda.

Para o upload de arquivos muito básico eu criei essa function de serviço como uma solução alternativa (usando a resposta do Тимофей ):

  uploadFile(file:File):Promise { return new Promise((resolve, reject) => { let xhr:XMLHttpRequest = new XMLHttpRequest(); xhr.onreadystatechange = () => { if (xhr.readyState === 4) { if (xhr.status === 200) { resolve(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); }); } 

seu arquivo de serviço 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; } } 

chame sua function (arquivo 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); }); } 

seu código html:

  

No meu projeto, eu uso o XMLHttpRequest para enviar multipart / form-data. Eu acho que vai caber em você.

e o código do uploader

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

Aqui está o exemplo: https://github.com/wangzilong/angular2-multipartForm

Primeiro, você tem que criar seu próprio TS-Class, já que a class FormData não é bem suportada no momento:

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

Então você envia para o servidor com JSON.stringify (data)

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