Угловой-пост загруженный файл
Я использую Угловое, TypeScript для отправки файла вместе с данными JSON на сервер.
Ниже приведен мой код:
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
});
}
}
как я могу преобразовать formData
в строку и отправить его на сервер? Я помню в AngularJS (v1) вы бы использовали transformRequest
.
5 ответов:
посмотрите на мой код, но помните. Я использую async / await, потому что последняя бета-версия Chrome может читать любой код es6, который получает по TypeScript с компиляцией. Таким образом, вы должны заменить asyns/await на
.then()
.обработчик изменения входного сигнала:
/** * @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; }
отправить обработчик:
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. Эта служба также хранит прогресс загрузки в progress$ property, а в других местах вы можете подписаться на нее и получать новое значение каждые 500 мс.
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); } }
глядя на эту проблему Github-запрос / загрузка обработки прогресса через @angular / http, angular2 http пока не поддерживает загрузку файлов.
для очень простой загрузки файлов я создал такую сервисную функцию как обходной путь (используя Тимофей это):
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); }); }
ваш 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; } }
вызовите функцию (файл компонента):
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); }); }
ваш html код:
<input type="file" class="form-control" name="documents" (change)="onChange($event)" [(ngModel)]="stock.documents" #documents="ngModel">
в моем проекте я использую XMLHttpRequest для отправки multipart/данные формы. Я думаю, что это подойдет вам.
и uploader код
let xhr = new XMLHttpRequest(); xhr.open('POST', 'http://www.example.com/rest/api', true); xhr.withCredentials = true; xhr.send(formData);
вот пример:https://github.com/wangzilong/angular2-multipartForm
во-первых, вы должны создать свой собственный встроенный TS-класс, так как класс FormData на данный момент не поддерживается:
var data : { name: string; file: File; } = { name: "Name", file: inputValue.files[0] };
затем вы отправляете его на сервер с помощью JSON.stringify (data)
let opts: RequestOptions = new RequestOptions(); opts.method = RequestMethods.Post; opts.headers = headers; this.http.post(url,JSON.stringify(data),opts);