Angular中的文件上传?

hem*_*123 160 file-upload angular2-http angular

我知道这是一个普遍的问题,但我没有在Angular 2上传文件.我试过了

1)http://valor-software.com/ng2-file-upload/

2)http://ng2-uploader.com/home

......但失败了.有人在Angular上传过文件吗?你用了什么方法?怎么办?如果提供任何示例代码或演示链接,我们将非常感激.

小智 362

Angular 2为上传文件提供了很好的支持.不需要第三方库.

<input type="file" (change)="fileChange($event)" placeholder="Upload file" accept=".pdf,.doc,.docx">

fileChange(event) {
    let fileList: FileList = event.target.files;
    if(fileList.length > 0) {
        let file: File = fileList[0];
        let formData:FormData = new FormData();
        formData.append('uploadFile', file, file.name);
        let headers = new Headers();
        /** In Angular 5, including the header Content-Type can invalidate your request */
        headers.append('Content-Type', 'multipart/form-data');
        headers.append('Accept', 'application/json');
        let options = new RequestOptions({ headers: headers });
        this.http.post(`${this.apiEndPoint}`, formData, options)
            .map(res => res.json())
            .catch(error => Observable.throw(error))
            .subscribe(
                data => console.log('success'),
                error => console.log(error)
            )
    }
}
Run Code Online (Sandbox Code Playgroud)

使用@ angular/core":"~2.0.0"和@ angular/http:"~2.0.0"

  • 如果Angular团队会写一些关于这个主题的文档,那就太棒了,我在他们的文档中找不到关于它的单行.此代码示例已过期,不适用于v4 +. (22认同)
  • 它对我有用,除了 - 我必须在这一行上工作 - header.append('enctype','multipart/form-data');`(用'enctype'代替'Content-Type').也许这取决于服务器端代码.(即api) (19认同)
  • 请注意,对于某些应用程序服务器,将拒绝设置内容类型.你需要让它为空:let headers = new Headers(); 浏览器会为您排序. (10认同)
  • LMFAO用这个垃圾挣扎了20分钟,直到我意识到我根本不需要设置标题.使用带有.Net webapi的angular 4.xx的其他人请注意,不要尝试设置标题!Thx用于指出@PeterS (6认同)
  • 它不起作用,至少在我的情况下.sailsJs服务器接收空文件数组/对象 (5认同)
  • 好的...我得到了必须写的网址. (3认同)
  • 我需要将其作为application/json上传,是否可能? (2认同)

Tar*_*ion 68

从上面的答案我用Angular 5.x构建它

只需致电uploadFile(url, file).subscribe()即可触发上传

import { Injectable } from '@angular/core';
import {HttpClient, HttpParams, HttpRequest, HttpEvent} from '@angular/common/http';
import {Observable} from "rxjs";

@Injectable()
export class UploadService {

  constructor(private http: HttpClient) { }

  // file from event.target.files[0]
  uploadFile(url: string, file: File): Observable<HttpEvent<any>> {

    let formData = new FormData();
    formData.append('upload', file);

    let params = new HttpParams();

    const options = {
      params: params,
      reportProgress: true,
    };

    const req = new HttpRequest('POST', url, formData, options);
    return this.http.request(req);
  }
}
Run Code Online (Sandbox Code Playgroud)

在组件中使用它

  // At the drag drop area
  // (drop)="onDropFile($event)"
  onDropFile(event: DragEvent) {
    event.preventDefault();
    this.uploadFile(event.dataTransfer.files);
  }

  // At the drag drop area
  // (dragover)="onDragOverFile($event)"
  onDragOverFile(event) {
    event.stopPropagation();
    event.preventDefault();
  }

  // At the file input element
  // (change)="selectFile($event)"
  selectFile(event) {
    this.uploadFile(event.target.files);
  }

  uploadFile(files: FileList) {
    if (files.length == 0) {
      console.log("No file selected!");
      return

    }
    let file: File = files[0];

    this.upload.uploadFile(this.appCfg.baseUrl + "/api/flash/upload", file)
      .subscribe(
        event => {
          if (event.type == HttpEventType.UploadProgress) {
            const percentDone = Math.round(100 * event.loaded / event.total);
            console.log(`File is ${percentDone}% loaded.`);
          } else if (event instanceof HttpResponse) {
            console.log('File is completely loaded!');
          }
        },
        (err) => {
          console.log("Upload Error:", err);
        }, () => {
          console.log("Upload done");
        }
      )
  }
Run Code Online (Sandbox Code Playgroud)

  • 适用于Angular6.谢谢.您需要导入这些库.从'@ angular/common/http'导入{HttpClient,HttpParams,HttpRequest,HttpEvent,HttpEventType,HttpResponse}; (6认同)
  • html 部分是这样的 `input type="file" (change)="addFiles($event)" style="display: none" #file multiple&gt; &lt;button mat-raised-button color="primary" (click) ="selectFile($event)"&gt;上传文件&lt;/button&gt;` (2认同)

hem*_*123 23

感谢@Eswar.这段代码非常适合我.我想在解决方案中添加某些内容:

我收到了错误: java.io.IOException: RESTEASY007550: Unable to get boundary for multipart

为了解决此错误,您应该删除"Content-Type""multipart/form-data".它解决了我的问题.

  • +1.如果删除Content-Type,则会正确生成.例如:`multipart/form-data; 边界= --------------------------- 186035562730765173675680113`.另请参阅http://stackoverflow.com/a/29697774/1475331和https://github.com/angular/angular/issues/11819. (5认同)

jsa*_*ter 18

由于代码示例有点过时,我想我会分享一个更近期的方法,使用Angular 4.3和新的(呃)HttpClient API,@ angular/common/http

export class FileUpload {

@ViewChild('selectedFile') selectedFileEl;

uploadFile() {
let params = new HttpParams();

let formData = new FormData();
formData.append('upload', this.selectedFileEl.nativeElement.files[0])

const options = {
    headers: new HttpHeaders().set('Authorization', this.loopBackAuth.accessTokenId),
    params: params,
    reportProgress: true,
    withCredentials: true,
}

this.http.post('http://localhost:3000/api/FileUploads/fileupload', formData, options)
.subscribe(
    data => {
        console.log("Subscribe data", data);
    },
    (err: HttpErrorResponse) => {
        console.log(err.message, JSON.parse(err.error).error.message);
    }
)
.add(() => this.uploadBtn.nativeElement.disabled = false);//teardown
}
Run Code Online (Sandbox Code Playgroud)


aba*_*het 15

在Angular 2+中,将Content-Type留空是非常重要的.如果您将"内容类型"设置为"multipart/form-data",则上传将无效!

upload.component.html

<input type="file" (change)="fileChange($event)" name="file" />
Run Code Online (Sandbox Code Playgroud)

upload.component.ts

export class UploadComponent implements OnInit {
    constructor(public http: Http) {}

    fileChange(event): void {
        const fileList: FileList = event.target.files;
        if (fileList.length > 0) {
            const file = fileList[0];

            const formData = new FormData();
            formData.append('file', file, file.name);

            const headers = new Headers();
            // It is very important to leave the Content-Type empty
            // do not use headers.append('Content-Type', 'multipart/form-data');
            headers.append('Authorization', 'Bearer ' + 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9....');
            const options = new RequestOptions({headers: headers});

            this.http.post('https://api.mysite.com/uploadfile', formData, options)
                 .map(res => res.json())
                 .catch(error => Observable.throw(error))
                 .subscribe(
                     data => console.log('success'),
                     error => console.log(error)
                 );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Joh*_*ird 8

我使用以下工具成功启动.我在游戏中没有使用primeNg的皮肤,只是传递了我的建议.

http://www.primefaces.org/primeng/#/fileupload


yon*_*bat 6

这个简单的解决方案对我有用:file-upload.component.html

<div>
  <input type="file" #fileInput placeholder="Upload file..." />
  <button type="button" (click)="upload()">Upload</button>
</div>
Run Code Online (Sandbox Code Playgroud)

然后使用XMLHttpRequest直接在组件中上传.

import { Component, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: 'app-file-upload',
  templateUrl: './file-upload.component.html',
  styleUrls: ['./file-upload.component.css']
})
export class FileUploadComponent implements OnInit {

  @ViewChild('fileInput') fileInput;

  constructor() { }

  ngOnInit() {
  }

  private upload() {
    const fileBrowser = this.fileInput.nativeElement;
    if (fileBrowser.files && fileBrowser.files[0]) {
      const formData = new FormData();
      formData.append('files', fileBrowser.files[0]);
      const xhr = new XMLHttpRequest();
      xhr.open('POST', '/api/Data/UploadFiles', true);
      xhr.onload = function () {
        if (this['status'] === 200) {
            const responseText = this['responseText'];
            const files = JSON.parse(responseText);
            //todo: emit event
        } else {
          //todo: error handling
        }
      };
      xhr.send(formData);
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是dotnet核心,则参数名称必须与from字段名称匹配.这种情况下的文件:

[HttpPost("[action]")]
public async Task<IList<FileDto>> UploadFiles(List<IFormFile> files)
{
  return await _binaryService.UploadFilesAsync(files);
}
Run Code Online (Sandbox Code Playgroud)

这个答案是http://blog.teamtreehouse.com/uploading-files-ajax的一个整体

编辑:上传后,您必须清除文件上传,以便用户可以选择新文件.而不是使用XMLHttpRequest,也许最好使用fetch:

private addFileInput() {
    const fileInputParentNative = this.fileInputParent.nativeElement;
    const oldFileInput = fileInputParentNative.querySelector('input');
    const newFileInput = document.createElement('input');
    newFileInput.type = 'file';
    newFileInput.multiple = true;
    newFileInput.name = 'fileInput';
    const uploadfiles = this.uploadFiles.bind(this);
    newFileInput.onchange = uploadfiles;
    oldFileInput.parentNode.replaceChild(newFileInput, oldFileInput);
  }

  private uploadFiles() {
    this.onUploadStarted.emit();
    const fileInputParentNative = this.fileInputParent.nativeElement;
    const fileInput = fileInputParentNative.querySelector('input');
    if (fileInput.files && fileInput.files.length > 0) {
      const formData = new FormData();
      for (let i = 0; i < fileInput.files.length; i++) {
        formData.append('files', fileInput.files[i]);
      }

      const onUploaded = this.onUploaded;
      const onError = this.onError;
      const addFileInput = this.addFileInput.bind(this);
      fetch('/api/Data/UploadFiles', {
        credentials: 'include',
        method: 'POST',
        body: formData,
      }).then((response: any) => {
        if (response.status !== 200) {
          const error = `An error occured. Status: ${response.status}`;
          throw new Error(error);
        }
        return response.json();
      }).then(files => {
        onUploaded.emit(files);
        addFileInput();
      }).catch((error) => {
        onError.emit(error);
      });
    }
Run Code Online (Sandbox Code Playgroud)

https://github.com/yonexbat/cran/blob/master/cranangularclient/src/app/file-upload/file-upload.component.ts