【问题标题】:How do you POST a FormData object in Angular 2?如何在 Angular 2 中发布 FormData 对象?
【发布时间】:2016-09-07 13:41:19
【问题描述】:

我需要上传一个文件并发送一些json,我有这个功能:

POST_formData(url, data) {
        var headers = new Headers(), authtoken = localStorage.getItem('authtoken');

        if (authtoken) {
            headers.append("Authorization", 'Token ' + authtoken)
        }

        headers.append("Accept", 'application/json');
        headers.delete("Content-Type");

        var requestoptions = new RequestOptions({
            method: RequestMethod.Post,
            url: this.apiURL + url,
            headers: headers,
            body: data
        })

        return this.http.request(new Request(requestoptions))

        .map((res: Response) => {
            if (res) {
                return { status: res.status, json: res.json() }
            }
        })
    }

我的问题是,如果我将 content-type 设置为“multipart/form-data”,我的服务器会抱怨边界,如果我完全删除 content-type 标头,我的服务器会抱怨它“text/plain”是受支持的媒体输入。

那么,如何使用 angular2 发送 FormData?

【问题讨论】:

  • 现在不支持 FormData。我可以在Request 类中看到一条待办事项评论// TODO: support URLSearchParams | FormData | Blob | ArrayBuffer
  • 用 Angular 2 做你现在所拥有的应该可以工作
  • 请注意,headers.delete("Content-Type") 对于文件上传非常重要。我正在这样做: headers.set("Content-Type", "") ,但这会导致角度用逗号附加 multipart/form-data 字符串(这将使其格式错误。我花了一整天的时间寻找对于这个解决方案。谢谢!

标签: angular typescript file-upload angular2-http


【解决方案1】:

是Angular2 Git Repository上的Open Isuue,还有一个Pull Request等待合并,希望快点合并。


或者,

为此,您可以直接使用XMLHttpRequest Object。

别忘了设置标题

xhr.setRequestHeader("enctype", "multipart/form-data");

// IE workaround for Cache issues
xhr.setRequestHeader("Cache-Control", "no-cache");
xhr.setRequestHeader("Cache-Control", "no-store");
xhr.setRequestHeader("Pragma", "no-cache");

在您制作的XMLHttpRequest 上。


类似问题:

How to upload file in Angular2

Angular 2 File upload from input type=file

Angular2 post uploaded file

【讨论】:

【解决方案2】:

我知道这已被标记为已回答并且已经很老了,但是我在将 FormData 对象发布到 OpenIdConnect AuthServer 时遇到了问题,并且上面的文件上传示例不是我想要的。

这是我获得 OpenIdAuthToken 的服务:

import { Injectable } from '@angular/core';
import { Http, RequestOptions, Headers, URLSearchParams} from '@angular/http'
import { OpenIdTokenRequest, SmartData } from '../model/openid-token-request';
import { OpenIdToken } from '../model/openid-token';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';
import { Observable } from 'rxjs';

@Injectable()

export class TokenService {

    constructor(private _http: Http) { }

    getToken(requestData: OpenIdTokenRequest, smartData: SmartData) {
        let _urlParams = new URLSearchParams();
        _urlParams.append('code', requestData.code);
        _urlParams.append('grant_type', requestData.grantType);
        _urlParams.append('redirect_uri', requestData.redirectUri);
        _urlParams.append('client_id', requestData.clientId);

        let _url = smartData.tokenUri;
        let _options = this.getTokenPostOptions();

        return this._http.post(_url, _urlParams, _options)
            .map(response => <OpenIdToken>response.json())
    }

    private getTokenPostOptions(): RequestOptions {

        let headers = new Headers({ 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' });
        let options = new RequestOptions({ headers: headers });

        return options;
    }

}

【讨论】:

    【解决方案3】:

    模板:

    <label class="btn btn-primary">
      <input type="file" style="display: none;" multiple="true" (change)="fileChange($event)" accept=".xml">
      <span>Click Me!</span>
    </label>
    

    UPD:Angular 5 - HttpClient + Typescript

    onFileUpload(event: EventTarget) {
    
      const eventObj: MSInputMethodContext = <MSInputMethodContext>event;
      const target: HTMLInputElement = <HTMLInputElement>eventObj.target;
      const files: FileList = target.files;
    
      const formData: FormData = new FormData();
    
      for (let i = 0; i < files.length; i++) {
        formData.append('file', files[i]);
      }
    
      // POST
      this.httpClient.post<AnalyzedData>(uploadUrl, formData).subscribe(...);
    }
    

    旧 Http 库 - Angular 4.3 之前

    fileChange(event) {
        let files = event.target.files;
            if (files.length > 0) {
            let formData: FormData = new FormData();
            for (let file of files) {
                 formData.append('files', file, file.name);
            }
            let headers = new Headers();
            headers.set('Accept', 'application/json');
            let options = new RequestOptions({ headers: headers });
            this.http.post(uploadURL, formData, options)
                .map(res => res.json())
                .catch(error => Observable.throw(error))
                .subscribe(
                data => {
                    // Consume Files
                    // ..
                    console.log('uploaded and processed files');
                },
                error => console.log(error),
                () => {
                    this.sleep(1000).then(() =>
                        // .. Post Upload Delayed Action
                    )
                });
        }
    }
    

    【讨论】:

    • 对我来说,缺少的重要行是:headers.set('Accept', 'application/json');
    • 请注意,这是旧版本的 Http,现在 (5.x) 已弃用。您应该使用来自@angular/common/httpHttpClient
    • 使用 Angular 5.2.3 和“UPD: Angular 5 - HttpClient + Typescript”解决方案对我来说可以上传 *.mp3 文件。在后端,我在 NodeJS 上使用了 Multer
    【解决方案4】:

    我解决了这个问题,根本不需要content-type

    请看这里,https://stackoverflow.com/a/45879409/2803344

    另请参阅此处以查看如何设置headersAngular2 - set headers for every request

    2017.8.25

    【讨论】:

      猜你喜欢
      • 2016-04-19
      • 2018-09-11
      • 1970-01-01
      • 2017-04-30
      • 2015-09-27
      • 2017-11-05
      • 2023-04-03
      • 2017-01-23
      • 1970-01-01
      相关资源
      最近更新 更多