I’ve been working on a web application with AngularJS for the past week.
AngularJS is awesome and so does Angular Material. Everything works fine until I tried to upload an image file and pass it together with some other form data to my backend. If you have the same issue as I did, please read on.
ng-flow
ng-flow is a pretty cool plugin that can upload file to a specific url. It comes with some cool features like drag and drop uploading, image preview, folder uploading etc. You can find out more at ng-flow.
Basic usage
The usage of ng-flow is simple as following:
Add the module to your app as a dependency:
angular.module("app", ["flow"]);
then use it in html:
<div
flow-init="{target: '/upload'}"
flow-files-submitted="$flow.upload()"
flow-file-success="$file.msg = $message"
>
<!-- Input or other element as upload button -->
<input type="file" flow-btn />
<span class="btn" flow-btn>Upload File</span>
<table>
<tr ng-repeat="file in $flow.files">
<img flow-img="file" height="150" width="150" />
</tr>
</table>
</div>
The input with flow-btn should do the upload job, the span will do the drag and drop job and the preview will be showed below the input area.
Together with form data
Here is how I uploaded file together with form-data:
In my HTML, find the file I’ve just uploaded (it’s in the $scope.files[0].file
). Then create a button that will start the whole upload process.
<md-button ng-click="upload($flow.files[0].file)"></md-button>
In my controller, I created a form data objecct first and fill it with my
data. Then call the upload service.
// create photo
$scope.upload = function (photo) {
// initialize form data var fd = new
FormData();
fd.append("a", angular.toJson("a"));
fd.append("b", angular.toJson("b"));
fd.append("c", angular.toJson("c"));
fd.append("photo", photo); // use photo service to create new photo
PhotoService.uploadPhoto(fd).then(
function (data) {
$scope.update(data);
},
function (data) {
console.error("upload failed", data);
}
);
};
Lastly, in my service, set the Content-Type
in http headers to undefined
so that it can be encoded in multipart/form-data
method when sending to the backend
// uploadPhoto:
function(photo) {
return $http({
method: 'POST',
url: myURL,
data: photo,
headers: {
'Content-Type': undefined,
transformRequest: angular.identity
}
}).then(
function(response) {
return response.data;
},
function(response) {
throw response.data;
}
);
}
Summary
There are four things need to do to upload files together with form data:
- find the file / photo
- create a form data object and fill it with file and data
- set http ‘Content-Type’ headers to undefined
- enjoy the photo uploading