如何在Angular2中上传文件
Posted
技术标签:
【中文标题】如何在Angular2中上传文件【英文标题】:How to upload file in Angular2 【发布时间】:2016-06-29 08:41:18 【问题描述】:我必须连同图片一起提交表格。我已经尝试过这段代码(有多种方式),但对我不起作用。有没有人有使用angular2上传文件的工作演示,请帮帮我。
component.html
<form class="form-horizontal" role="form" >
<div class="form-group">
<label class="control-label col-sm-4" for="myname" style="">Name<span class="asterisk">*</span></label>
<div class="col-sm-7">
<div>
<input type="text" class="form-control" id="myname"
[(ngModel)]="myfile.name">
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-4" for="myimage">Image</label>
<div class="col-sm-7">
<div>
<input type="file" (change)="fileChangeEvent($event)" placeholder="Upload file..." />
</div>
</div>
</div>
<div class="form-group">
<div class="text-center">
<button type="button" (click)="upload()">Upload</button>
</div>
</div>
</form>
组件.ts
myfile=
"name":"Mubashshir",
"image":''
fileChangeEvent(fileInput: any)
this.myfile.image = fileInput.target.files;
upload()
this.base_path_service.PostRequest('http://128.199.190.109/api/school/schoolDetail/',this.myfile)
.subscribe(
data =>
console.log("data submitted");
,
err => console.log(err),
() =>
console.log('Authentication Complete');
);
【问题讨论】:
见***.com/a/39862337/3779853 【参考方案1】:事实上,Http
类目前不支持。
您需要利用底层 XHR 对象来做到这一点:
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);
);
查看此 plunkr 了解更多详情:https://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=info。
在 Angular 存储库中有一个问题和待处理的 PR:
https://github.com/angular/angular/issues/10424 https://github.com/angular/angular/pull/7310/files【讨论】:
你怎么能得到这个响应?现在不应该是 Promise 而不是 Observable 吗? 嘿,我得到这个答案的解析错误。例外:SyntaxError:JSON.parse:JSON datavendor.js 的第 1 行第 1 列出现意外字符:1617 例外:SyntaxError:JSON.parse:JSON datavendor.js 第 1 行第 1 列出现意外字符:1617:2286 STACKTRACE: vendor.js:1617:2286 ......还有其他人遇到这个问题吗? 在 Angular 的最终版本中,您不再需要处理底层 XHR 对象,请参阅此答案:***.com/a/39862337/3351622【参考方案2】:您的 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">
【讨论】:
这个不行,因为http post不支持FormData,你的数据不会传到服务器,github.com/angular/angular/issues/13241【参考方案3】:改进的 onChange() 方法:
file: File;
onChange(event: EventTarget)
let eventObj: MSInputMethodContext = <MSInputMethodContext> event;
let target: HTMLInputElement = <HTMLInputElement> eventObj.target;
let files: FileList = target.files;
this.file = files[0];
console.log(this.file);
【讨论】:
终于,我得到了一个文件对象!!【参考方案4】:这是 Angular 2 版本
我们需要在我们的Angular 2 应用之一中实现拖放文件输入功能。
我们为此选择了ng-file-upload。
我们尝试关注help page。按照建议,实现 drag-upload-input.html
和 drag-upload-input.component.ts
如下:
拖动上传输入.html
<!-- we only need single file upload -->
<input type="file" ng2FileSelect [uploader]="uploader" />
拖动上传输入.component.ts
import Component from '@angular/core';
import FileUploader from 'ng2-file-upload';
// const URL = '/api/';
const URL = 'https://evening-anchorage-3159.herokuapp.com/api/';
@Component(
moduleId: module.id,
selector: 'drag-upload-input',
templateUrl: './drag-upload-input.html'
)
export class DragUploadInput
public uploader: FileUploader = new FileUploader( url: URL );
public hasBaseDropZoneOver: boolean = false;
public hasAnotherDropZoneOver: boolean = false;
public fileOverBase(e: any): void
this.hasBaseDropZoneOver = e;
public fileOverAnother(e: any): void
this.hasAnotherDropZoneOver = e;
app.module.ts
有这样的FileUploadModule
:
// File upload modules
import FileUploadModule from 'ng2-file-upload';
import DragUploadInput from './file-upload/drag-upload-input.component';
//other imports
@NgModule(
imports: [ ... other imports
FileUploadModule
],
declarations: [ ... other declarations
DragUploadInput],
bootstrap: [AppComponent]
)
export class AppModule
systemjs.config.js
看起来像这样:
(function (global)
System.config(
// map tells the System loader where to look for things
map:
// other libraries
'ng2-file-upload': 'node_modules/ng2-file-upload',
,
packages:
// other packages
ng2-file-upload':
main: 'ng2-file-upload.js',
defaultExtension: 'js'
);
)(this);
source
【讨论】:
嘿,文件上传到哪里了?我们如何配置它?以上是关于如何在Angular2中上传文件的主要内容,如果未能解决你的问题,请参考以下文章
通过 multipart/form-data 上传 Angular2 文件,400 错误
在 Angular 2 和 Spring MVC 中上传带有其他表单字段的文件