I am trying to upload files through my web app using the following code.
View:
<form name="uploadForm" class="form-horizontal col-sm-12">
<div class="col-sm-4">
<input type="file" ng-model="rsdCtrl.viewData.file" name="file"/>
</div>
<div class="col-sm-4">
<button class="btn btn-success" type="submit" ng-click="uploadFile()">Upload</button>
</div>
</form>
Controller:
function uploadFile(){
if (uploadForm.file.$valid && file) {
return uploadService.upload(vd.file, "Convictions Calculator", "PCCS").then(function(response){
/* Some stuff */
}).catch(handleServiceError);
}
}
uploadService:
(function (){
'use strict';
angular.module('cica.common').service('uploadService', ['$http', '$routeParams', uploadService]);
function uploadService($http, $routeParams) {
this.upload = function (file, name, type) {
const fd = new FormData();
fd.append('document', file);
fd.append('jobId', $routeParams.jobId);
fd.append('documentRename', name);
fd.append('documentType', type);
return $http.post('/document/upload', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).catch(function(err){
handleHttpError('Unable to upload document.', err);
});
};
}
})();
routes.js:
'POST /document/upload': {controller: 'DocumentController', action: 'uploadDocument'},
DocumentController:
"use strict";
const fs = require('fs');
module.exports = {
uploadDocument: function (req, res) {
console.log(req.allParams()); //Inserted as part of debugging
const params = req.allParams();
req.file('document').upload({
// don't allow the total upload size to exceed ~100MB
maxBytes: 100000000
}, function whenDone(err, uploadedFiles) {
if (err) {
return res.serverError(err);
}
// If no files were uploaded, respond with an error.
else if (uploadedFiles.length === 0) {
return res.serverError('No file was uploaded');
} else {
const filePath = uploadedFiles[0].fd;
const filename = uploadedFiles[0].filename;
return fs.readFile(filePath, function (err, data) {
if (err) {
return res.serverError(err);
} else {
const jobId = params.jobId;
const jobVars =
{
filePath: results.filePath,
fileName: params.documentRename,
fileType: params.documentType
};
return DocumentService.uploadConvictions(req.session.sessionId, jobId, jobVars).then(function (response) {
return res.send("Document uploaded.");
}).catch(function (err) {
return res.serverError(err);
});
}
});
}
});
},
If I upload a .jpeg (around 11kB) the upload works exactly as expected, however, if I try to upload a larger .jpeg (around 170kB) it falls over. There is no immediate error thrown/caught though, what happens is the formData object created in the upload service seems to lose its data. If I breakpoint on its value, it returns empty for the larger file, which eventually causes an error when the function tries to use these variables further on. Is there some kind of limit set to the size of a file you can upload via this method, or have I configured this incorrectly?
Avoid using the FormData API when Uploading Large Files1
The FormData API encodes data in base64 which add 33% extra overhead.
Instead of sending
FormData
, send the file directly:When the browser sends
FormData
, it uses'Content-Type': multipart/formdata
and encodes each part using base64.When the browser sends a file (or blob), it sets the content type to the MIME-type of the file (or blob). It puts the binary data in the body of the request.
How to enable
<input type="file">
to work withng-model
2Out of the box, the
ng-model
directive does not work withinput type="file"
. It needs a directive:Usage:
I take the chance and assume you are using
bodyParser
as middleware. bodyParser has a defaultlimit
of 100kb. Look atnode_modules/body-parser/lib/types/urlencoded.js
:You can change the limit in your
app.js
by