multer array upload does not upload files, getting an empty array - arrays

Want to upload an array of 3 files, but in my nodejs i get only an empty array from the angular controller.
In my angular controller i get the files from html with an onchange method, and send it with an http request to the upload function in my nodejs backend.
this.selectFile1 = function(files){
fileArray[0] = files[0];
self.files = files;
}
this.selectFile2 = function(files){
fileArray[1] = files[0];
self.files = files;
}
this.selectFile3 = function(files){
fileArray[2]= files[0];
self.files = files;
}
this.upload = function(){
var fd = new FormData();
var file = fileArray;
fd.append('file', file);
$http.post("/upload", fd, {
transformRequest: angular.identity,
headers: {"Content-Type": undefined}
}).then(function success(response){
if(response.status == 200){
console.log('success');
}
}, function error(response){
console.log(response.data.msgUpload);
})
}
Nodejs upload function:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../uploads');
}
});
var upload = multer({ storage : storage});
router.post('/upload', upload.array('file', 3), function(req,res, next){
console.log(req.files);
if(!req.files){
res.status(400);
}else{
res.status(200);
}
});
why do I get an empty array? and how can I insert the files which are to be uploaded?

Related

How to get header information using http in angularjs?

Here I have hard coded fileName but I want to get the filename from my spring service where I have already set the file name in header of http response. How to get the file name at js end.
$http.post('/myrest/rest/getVendorExcelDownload',$scope.exelReportInputDTO,{responseType: 'arraybuffer'})
.success(function(data, status, headers, config){
console.log("inside success");
var fileName = "Vendor_Excel_Reports.xls";
var a = document.createElement("a");
var blob = new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
var objectUrl = URL.createObjectURL(blob);
a.href = objectUrl;
a.download = fileName;
a.click();
}).error(function(data){
console.log("inside error");
});
You can try to get filename from header like this ..
var req = {
method: 'POST',
url: '', //your API
headers: {
id: id // get your filename from header
}
}
$http(req)
.then(function mySucces(response) {
//your success code!
},
function myError(response) {
//your error code!
});

File Upload nodejs, angularjs : Form mistake?

I have a multer file upload which does nothing, it doesn't even give me an error. My opiniion is that this is a form mistake, that the html form can't tell the angular controller to send the http post to the nodejs
upload.html
<form id="uploadForm" ng-submit="ctrl.submit">
Select File1: <input type="file" name="file" onchange="angular.element(this).scope().ctrl.selectFile1(this.files)">
<p></p>
Select File2: <input type="file" name="file" onchange="angular.element(this).scope().ctrl.selectFile2(this.files)">
<p></p>
<br>
<input type="submit" value="Upload" id="submit" class="btn btn-primary" ng-click="ctrl.submit()">
</form>
AngularJS Controller
ctrl.js
var file1 = '';
var file2 = '';
this.selectFile1 = function(files){
file1 = files[0];
this.files = files;
}
this.selectFile2 = function(files){
file2 = files[0];
this.files = files;
}
this.upload = function(){
var fd = new FormData();
var file = self.fileArray;
fd.append('file1', file1);
fd.append('file2', file2);
$http.post("/upload", fd, {
transformRequest: angular.identity,
headers: {"Content-Type": undefined}
}).then(function success(response){
if(response.status == 200){
console.log('success');
}
console.log(response);
}, function error(response){
console.log(response);
})
}
NodeJS Backend
test.js
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../uploads');
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
var upload = multer({ storage : storage}).array('file', 2);
router.post('/upload', function(req, res){
upload(req, res, function(err){
if(err){
console.log(err);
return res.end(err);
}
console.log(req.files);
res.sendStatus(200);
});
});
I can save the files from html to the angular controller and save them to the form data but when I send the form data with an array of 2 files to the nodejs backend I get an empty form data in the backend.
SOLUTION:
in nodejs file changed var upload = multer({ storage : storage}).array(...) to var upload = multer({ storage : storage}).any();
You can use onchange to select the file.
<input type="file" name="file" onchange="angular.element(this).scope().selectFile(this.files)"/>
<button ng-click="savePhoto()">Save </button>
In angular controller
xx.controller('yourcontroller', function($scope, $http){
$scope.selectFile = function (files) {
$scope.files = files;
};
$scope.savePhoto = function () {
var fd = new FormData();
fd.append("file", $scope.files[0]);
)) ;
$http.post("/xxx/photos", fd, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (data) {
$scope.image = data; // If you want to render the image after successfully uploading in your db
});
};
});

Angular FIle upload Custom headers for upload all

I want to add custom headers to a file before Uploading. Both methods below are not working:
$scope.uploadallman = function (qID) {
alert(qID);
uploader.headers = { QuestionID: qID };
//item.headers = {
// MyHeader: qID,
//};
uploader.uploadAll();
}
Maybe not the best solution, but it's the way I do it and it's working.
function _uploadFile(resourceURL, file) {
var deferred = $q.defer();
var config = {};
config.headers = {};
config.transformRequest = angular.identity;
config.headers['Content-Type'] = undefined;
// config.headers['MyCustomHeaderKey'] = MyCustomHeaderValue; // Optional
var formData = new FormData();
formData.append('file', file);
// formData.append('myCustomFormDataAttributeKey', myCustomFormDataAttributeValue); // Optional
$http.post(resourceURL, formData, config)
.success(function (response) {
deferred.resolve(response);
})
.error(function (err, status) {
deferred.reject(err);
});
return deferred.promise;
}
This is very good topic about the file upload in Angular:
How to POST JSON and a file to web service with Angular?

using ng-file-upload to upload file to hard drive

I want to use ng-file-upload to upload files to hard drive in the server
this.uploadFiles = function(files, errFiles) {
this.files = files;
this.errFiles = errFiles;
angular.forEach(files, function(file) {
file.upload = Upload.upload({
url: 'C:\Java\logs',
data: {file: file}
});
file.upload.then(function (response) {
$timeout(function () {
file.result = response.data;
});
}, function (response) {
if (response.status > 0)
this.errorMsg = response.status + ': ' + response.data;
}, function (evt) {
file.progress = Math.min(100, parseInt(100.0 *
evt.loaded / evt.total));
});
});
}
when I use this code I get this error
angular.js:10765 XMLHttpRequest cannot load file:///C:/Javalogs. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
that what I did but it didn't work
this.uploadFiles = function(file, errFiles) {
Upload.dataUrl(file[0], true).then(function (base64Url) {
var filename = 'test.jpg';
var a = document.createElement("a");
var myDocument = getFileContainer(base64Url);
var blob = new Blob([myDocument.data], {type: 'image/jpg'});
var file = new File([blob], 'imageFileName.jpg');
if(window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
}
else{
var elem = window.document.createElement('a');
elem.href = window.URL.createObjectURL(file);
elem.download = filename;
document.body.appendChild(elem);
elem.click();
document.body.removeChild(elem);
}
})
the picture is generated but I can't view it
I send them via a base64 url to the backend. It depends on which data you need but it should roughly look like the following code.
function getMimeTypeFromUrl(imageUrl) {
return imageUrl.substring(imageUrl.indexOf(':') + 1, imageUrl.indexOf(';'));
}
function getDataFromUrl(imageUrl){
return imageUrl.substring(imageUrl.indexOf(',') + 1);
}
function getFileContainer(imageUrl, file){
return {
data:getDataFromUrl(imageUrl),
mimeType: getMimeTypeFromUrl(imageUrl),
filename: file.name,
}
}
this.uploadFiles = function(files, errFiles) {
Upload.dataUrl(file, true).then(function (base64Url) {
myDocument = getFileContainer(base64Url, file);
//here you have to post myDocument
}
}
Upload is a service of ng-file-upload, which loads the file to the browser as a base64 url.
I hope I could help you.

Opening a pdf with angular ngResource from an MVC post request

I have a POST request for a PDF document in an APIController, here's the code:
Generator pdfGenerator = new Generator();
MemoryStream ms = pdfGenerator.Generate();
var response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(ms)
};
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Tag.pdf"
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return response;
when I send my file to angular with a GET request everything works fine and I can download the pdf using:
$window.open('my_url');
A well formed 28K pdf file is created in the download folder.
But when I changed my request to a POST the file is malformed.
var pdfGetter = $resource('my_url', {}, {
sendPDFTag: { method: 'POST', url: 'my_url', responseType: 'arraybuffer' }
});
pdfGetter.sendPDFTag(info, function(data) {
var file = new Blob([data], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
$window.open(fileURL);;
});
I tried using the FileSaver.js and I get a bad 1K pdf file in my download folder.
pdfGetter.sendPDFTag(info, function(data) {
var file = new Blob([data], { type: 'application/pdf' });
saveAs(file, 'Tag.pdf');
});
What could the problem be?
Thanks
I found the solution to my problem in this question: pdf-js-render-pdf-using-an-arraybuffer-or-blob-instead-of-url
The problem was with the ng-resource that returns a promise instead of the arraybuffer, so you need to transform the data before you process the promise.
Here is the corrected code:
var pdfGetter = $resource(myUrl, {}, {
sendPDFTag: { method: 'POST', url: myUrl + "/getPdfWithPost", responseType: 'arraybuffer',
transformResponse: function(data, headersGetter) {
// Stores the ArrayBuffer object in a property called "data"
return { data : data };
}
}
});
var pdfGetter = pdfGetter.sendPDFTag(info);
pdfGetter.$promise.then(function () {
var data = pdfGetter.data;
var file = new Blob([data], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
$window.open(fileURL);
});
Thank you

Resources