Angular - POST上传文件

28 浏览
0 Comments

Angular - POST上传文件

我正在使用Angular和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: `

文件上传

选择文件:

`

})

export class FileUploadCmp {

public file: File;

public url: string;

headers: Headers;

constructor(public http: Http) {

console.log('文件上传已初始化');

//设置头部为multipart

this.headers = new Headers();

this.headers.set('Content-Type', 'multipart/form-data');

this.url = 'http://localhost:8080/test';

}

//文件改变监听器

changeListener($event): void {

this.postFile($event.target);

}

//发送文件到服务器

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。

0
0 Comments

Angular - POST上传文件的问题出现的原因是因为Angular2的http模块尚不支持文件上传。为了解决这个问题,可以使用以下的服务函数作为一种解决方法:

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);
  });
}

然而,为了使其工作,需要在xhr.open的行之后添加`xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');`。如果需要授权,可以在xhr.open的行之后添加`xhr.setRequestHeader('Authorization', 'Bearer ' + __your_auth_key__);`。

目前还不支持文件上传,可以查看问题状态github.com/angular/http/issues/75。虽然链接已更新,但仍然没有直接支持进度,因为fetch功能缺乏此功能,而Angular不希望将http API与XHR绑定在一起。

我正在使用全新的Angular 4,似乎他们还没有修复这个问题。要么是我没理解对,要么就是文件从未传递过来。谢谢你的函数,我让它工作了。谢谢你。

目前还没有来自Angular的支持-github.com/angular/angular/issues/37597

0
0 Comments

Angular - POST上传文件

问题的出现原因:

在调用postWithFile函数时,未正确传递文件。在调用函数的组件文件中,通过event对象获取上传的文件,但是代码中却错误地使用了event.srcElement.files来获取文件,导致出现了"error TS2339: Property 'files' does not exist on type 'Element'."的错误。

解决方法:

在调用函数的组件文件中,将onChange函数修改为onChange(event),以正确传递event对象。这样就可以通过event.target.files来获取文件。

整理代码如下:

你的http服务文件:

import { Injectable } from "/core";
import { ActivatedRoute, Router } from '/router';
import { Http, Headers, Response, Request, RequestMethod, URLSearchParams, RequestOptions } from "/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 returnResponse = 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 returnResponse;
  }
}

调用你的函数(组件文件):

onChange(event) {
    let files = event.target.files;
    let postData = {field1: "field1", field2: "field2"}; // Put your form data variable. This is only an example.
    
    this._service.postWithFile(this.baseUrl + "add-update", postData, files).then(result => {
        console.log(result);
    });
}

你的HTML代码:


其中一个唯一使用了Angular的答案

如何解决"error TS2339: Property 'files' does not exist on type 'Element'."错误

onChange() {...}修改为onChange(event) {...}将修复错误:property files does not exist 😉

对我不起作用。它无法在后端使用multer的节点中找到该文件。

0
0 Comments

问题的出现原因:在上传文件时,代码中使用了async/await来处理异步操作,但最新的Chrome浏览器beta版本可以读取任何通过TypeScript编译的es6代码,因此必须将asyns/await替换为.then()。

解决方法:将代码中的async/await替换为.then()。

文章如下:

文件上传问题 - Angular中的POST上传文件

最近我在编写代码时遇到了一个问题,但请注意,我使用了async/await,因为最新的Chrome浏览器beta版本可以读取任何通过TypeScript编译的es6代码。所以,你必须将asyns/await替换为.then()。

下面是我代码中的一部分:

文件输入变化处理程序:

/**
 *  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 {
    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);
}

文件上传服务:

import { Component } from 'angular2/core';
import { Injectable } from 'angular2/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/share';
export class FileUploadService {
    private progress$: Observable;
    private progress: number = 0;
    private progressObserver: any;
    constructor() {
        this.progress$ = new Observable(observer => {
            this.progressObserver = observer
        });
    }
    public getObserver(): Observable {
        return this.progress$;
    }
    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);
        });
    }
    private static setUploadUpdateInterval(interval: number): void {
        setInterval(() => { }, interval);
    }
}

此外,我还需要添加以下代码才能使其正常工作:

xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

在上传XML文件时,它会自动在文件中添加' ------WebKitFormBoundaryklb8qUzyCQJSI440 Content-Disposition: form-data; name="file" '。我不想在传输过程中添加额外的数据到文件中,你知道如何解决吗?另外,上传jpg格式的图片后,它不再是jpg文件了。所以我的问题是:如何在传输过程中保持原始文件?

为什么我们需要setInterval()

希望以上内容能帮助到你。

0