如何在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.htmldrag-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中上传文件的主要内容,如果未能解决你的问题,请参考以下文章

Angular2 Ng2文件上传CORS问题

使用 Angular2 将文件上传到 REST API

通过 multipart/form-data 上传 Angular2 文件,400 错误

在 Angular 2 和 Spring MVC 中上传带有其他表单字段的文件

如何在服务和指令脚本文件中使用angular2内置日期管道[重复]

在 Angular 中上传文件?