Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send multipart/form-data files with angular using $http

I know there are a lot of questions about this, but I can't get this to work:

I want to upload a file from input to a server in multipart/form-data

I've tried two approaches. First:

headers: {   'Content-Type': undefined }, 

Which results in e.g. for an image

Content-Type:image/png 

while it should be multipart/form-data

and the other:

headers: {   'Content-Type': multipart/form-data }, 

But this asks for a boundry header, which I believe should not be manually inserted...

What is a clean way to solve this problem? I've read that you can do

$httpProvider.defaults.headers.post['Content-Type'] = 'multipart/form-data; charset=utf-8'; 

But I don't want all my posts to be multipart/form-data. The default should be JSON

like image 683
Thomas Stubbe Avatar asked Mar 01 '16 11:03

Thomas Stubbe


People also ask

How do you send a file using multipart form data?

Follow this rules when creating a multipart form: Specify enctype="multipart/form-data" attribute on a form tag. Add a name attribute to a single input type="file" tag. DO NOT add a name attribute to any other input, select or textarea tags.


2 Answers

Take a look at the FormData object: https://developer.mozilla.org/en/docs/Web/API/FormData

this.uploadFileToUrl = function(file, uploadUrl){         var fd = new FormData();         fd.append('file', file);         $http.post(uploadUrl, fd, {             transformRequest: angular.identity,             headers: {'Content-Type': undefined}         })         .success(function(){         })         .error(function(){         });     } 
like image 65
jstuartmilne Avatar answered Sep 16 '22 19:09

jstuartmilne


Here's an updated answer for Angular 4 & 5. TransformRequest and angular.identity were dropped. I've also included the ability to combine files with JSON data in one request.

Angular 5 Solution:

import {HttpClient} from '@angular/common/http';  uploadFileToUrl(files, restObj, uploadUrl): Promise<any> {   // Note that setting a content-type header   // for mutlipart forms breaks some built in   // request parsers like multer in express.   const options = {} as any; // Set any options you like   const formData = new FormData();    // Append files to the virtual form.   for (const file of files) {     formData.append(file.name, file)   }    // Optional, append other kev:val rest data to the form.   Object.keys(restObj).forEach(key => {     formData.append(key, restObj[key]);   });    // Send it.   return this.httpClient.post(uploadUrl, formData, options)     .toPromise()     .catch((e) => {       // handle me     }); } 

Angular 4 Solution:

// Note that these imports below are deprecated in Angular 5 import {Http, RequestOptions} from '@angular/http';  uploadFileToUrl(files, restObj, uploadUrl): Promise<any> {   // Note that setting a content-type header   // for mutlipart forms breaks some built in   // request parsers like multer in express.   const options = new RequestOptions();   const formData = new FormData();    // Append files to the virtual form.   for (const file of files) {     formData.append(file.name, file)   }    // Optional, append other kev:val rest data to the form.   Object.keys(restObj).forEach(key => {     formData.append(key, restObj[key]);   });    // Send it.   return this.http.post(uploadUrl, formData, options)     .toPromise()     .catch((e) => {       // handle me     }); } 
like image 36
Josh Hibschman Avatar answered Sep 20 '22 19:09

Josh Hibschman