I'm a beginner to angular.js but I have a good grasp of the basics.
What I am looking to do is upload a file and some form data as multipart form data. I read that this isn't a feature of angular, however 3rd party libraries can get this done. I've cloned angular-file-upload via git, however I am still unable to post a simple form and a file.
Can someone please provide an example, html and js of how to do this?
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.
Multipart upload allows you to upload a single object as a set of parts. Each part is a contiguous portion of the object's data. You can upload these object parts independently and in any order. If transmission of any part fails, you can retransmit that part without affecting other parts.
The FormData. entries() method provides an iterator for going through all key/value pairs of the instance. The FormData. get() method Returns the first value associated with a given key from within a FormData object.
First of all
<input accept="image/*" name="file" ng-value="fileToUpload" value="{{fileToUpload}}" file-model="fileToUpload" set-file-data="fileToUpload = value;" type="file" id="my_file" />
1.2 create own directive,
.directive("fileModel",function() { return { restrict: 'EA', scope: { setFileData: "&" }, link: function(scope, ele, attrs) { ele.on('change', function() { scope.$apply(function() { var val = ele[0].files[0]; scope.setFileData({ value: val }); }); }); } } })
$httpProvider.defaults.headers.post['Accept'] = 'application/json, text/javascript'; $httpProvider.defaults.headers.post['Content-Type'] = 'multipart/form-data; charset=utf-8';
Then create separate function in controller to handle form submit call. like for e.g below code:
In service function handle "responseType" param purposely so that server should not throw "byteerror".
transformRequest, to modify request format with attached identity.
withCredentials : false, for HTTP authentication information.
in controller: // code this accordingly, so that your file object // will be picked up in service call below. fileUpload.uploadFileToUrl(file); in service: .service('fileUpload', ['$http', 'ajaxService', function($http, ajaxService) { this.uploadFileToUrl = function(data) { var data = {}; //file object var fd = new FormData(); fd.append('file', data.file); $http.post("endpoint server path to whom sending file", fd, { withCredentials: false, headers: { 'Content-Type': undefined }, transformRequest: angular.identity, params: { fd }, responseType: "arraybuffer" }) .then(function(response) { var data = response.data; var status = response.status; console.log(data); if (status == 200 || status == 202) //do whatever in success else // handle error in else if needed }) .catch(function(error) { console.log(error.status); // handle else calls }); } } }])
<script src="//unpkg.com/angular/angular.js"></script>
This is pretty must just a copy of that projects demo page and shows uploading a single file on form submit with upload progress.
(function (angular) { 'use strict'; angular.module('uploadModule', []) .controller('uploadCtrl', [ '$scope', '$upload', function ($scope, $upload) { $scope.model = {}; $scope.selectedFile = []; $scope.uploadProgress = 0; $scope.uploadFile = function () { var file = $scope.selectedFile[0]; $scope.upload = $upload.upload({ url: 'api/upload', method: 'POST', data: angular.toJson($scope.model), file: file }).progress(function (evt) { $scope.uploadProgress = parseInt(100.0 * evt.loaded / evt.total, 10); }).success(function (data) { //do something }); }; $scope.onFileSelect = function ($files) { $scope.uploadProgress = 0; $scope.selectedFile = $files; }; } ]) .directive('progressBar', [ function () { return { link: function ($scope, el, attrs) { $scope.$watch(attrs.progressBar, function (newValue) { el.css('width', newValue.toString() + '%'); }); } }; } ]); }(angular));
HTML
<form ng-submit="uploadFile()"> <div class="row"> <div class="col-md-12"> <input type="text" ng-model="model.fileDescription" /> <input type="number" ng-model="model.rating" /> <input type="checkbox" ng-model="model.isAGoodFile" /> <input type="file" ng-file-select="onFileSelect($files)"> <div class="progress" style="margin-top: 20px;"> <div class="progress-bar" progress-bar="uploadProgress" role="progressbar"> <span ng-bind="uploadProgress"></span> <span>%</span> </div> </div> <button button type="submit" class="btn btn-default btn-lg"> <i class="fa fa-cloud-upload"></i> <span>Upload File</span> </button> </div> </div> </form>
EDIT: Added passing a model up to the server in the file post.
The form data in the input elements would be sent in the data property of the post and be available as normal form values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With