在angular2中上传文件:正文(FormData)为空

Posted

技术标签:

【中文标题】在angular2中上传文件:正文(FormData)为空【英文标题】:Upload file in angular2: Body (FormData) empty 【发布时间】:2017-06-14 21:47:49 【问题描述】:

我正在尝试将使用 Angular2 的图片上传到我的 REST 服务(环回)。 Loopback 服务有效(使用 Postman 测试)并接受带有 x-www-form-urlencoded 标头的文件。

这是发送 POST 请求的简化服务方法:

public uploadFile(url : string, file: File): Observable<any> 
  let headers: Headers = new Headers();
  headers.append('Content-Type', 'application/x-www-form-urlencoded');

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

  let options: RequestOptionsArgs =  headers: headers ;

  return this.http.post(url, formData, options)
  .map((res: any) => (res.text() != "" ? res.json() : ));

请注意,我已将标头设置为 application/x-www-form-urlencoded 并在正文中发送包含文件的 formData。

在 Angular 中,直到我 http.post 请求为止,formData 都填充了文件,文件内容存在,一切都很好:

Data before Request

但是在请求中,body是一个空对象:

Request

我假设,Angular 正在尝试做 JSON.stringify(formData),至少,当我尝试这个时,我也会得到“”作为输出。

我看到很多帖子都做同样的事情(http.post(url, formData))。那么我错过了什么?

【问题讨论】:

您是否尝试将 blob 数据提供给表单? 奇怪。我最近创建了一个Plunker 来回答类似的问题,如您所见,只需发布​​formData 即可。 AFAIK,Angular 不会自动 JSON.stringify(formData)。它会按原样发布您传递的内容。 控制台打印了什么? 我也这样做了。您是否 100% 确定您的“文件”已设置为某些内容? @AngularFrance 感谢 Plunker!我将它与我的代码进行了比较并观察了输出,它是如此相似,而且所有数据都已设置,真的很奇怪!我尝试从请求中删除选项,因为我认为这是我们解决方案之间唯一不同的方面。现在它可以工作了。然后请求带有 multipart/form-data 但有趣的是我的 Loopback 服务并不关心。但是,这仍然有点令人沮丧。想知道为什么它不适用于 urlencoded 【参考方案1】:

删除headers.append('Content-Type', 'multipart/form-data');即可解决问题。

见here

2017-08-24

【讨论】:

这为我解决了这个问题,使用 Web Api 2 和 Angular 4 这是为什么呢? headers.append('Content-Type', 'multipart/form-data') 有什么问题? 你能看看我的问题吗:***.com/questions/49942899/upload-file-in-angular-5 请看这个包github.com/bleenco/ngx-uploader,我找到的最好的文件上传器。 @OnnaB【参考方案2】:

从这个How to inspect FormData? SO 答案和这个MDN documentation 在控制台中输出FormData 只会导致

FormData 可以直接用在for ... of 结构中,而不是entries()for (var p of myFormData) 等价于for (var p of myFormData.entries())

【讨论】:

【参考方案3】:

还有另一种解决方案是使用 base64 并在后端进行转换: `

var reader = new FileReader();
    reader.readAsDataURL(file);
    let res;
    reader.onload = function () 
    let headers = new Headers();
    headers.append("Content-type","application/x-www-form-urlencoded");
    headers.append('Accept', 'application/json');
    let options = new RequestOptions( headers: headers );
    return this.http.post(config.serverUrl+"/index.php",
      
         "file":reader.result, options)
         .toPromise()
         .then(this.extractData)
         .catch(this.handleError);
      
    ;
    reader.onerror = function (error) 
        console.log('Error: ', error);
    ;`

【讨论】:

【参考方案4】:

在我的例子中,我使用了 formData.set() 而不是 formData.append()

请看下面的例子:

 UploadFile(fileToUpload: File): Observable<boolean> 
     const endpoint = 'api/image/upload';
     var formData = new FormData();
     formData.set('file', fileToUpload);
     return this._http
     .post(endpoint, formData)
     .map(() =>  return true; )
     .catch((e) => this.handleError(e));
 

【讨论】:

以上是关于在angular2中上传文件:正文(FormData)为空的主要内容,如果未能解决你的问题,请参考以下文章

Vue+ FormData 实现上传文件

Vue+ FormData 实现上传文件

如何在Angular2中上传文件

浅谈文件上传

浅谈文件上传

Angular2 Ng2文件上传CORS问题