How to prompt save dialog to download file using angularjs? - javascript

I have a directory in server that contains file now i am sending file name from client and getting the file from server till that part is working good, below is the response from server now once i receive response i want to prompt for user to download that file for that i am trying to create blob using Angularjs but its not prompting for user to save the file. Any idea ?
ctrl.js
$scope.downloadFile = function(message){
DitFactory.getFile(message).then(function(response){
console.log('r',response);
var blob = new Blob([ response ], { type : 'text/plain' });
$scope.url = (window.URL || window.webkitURL).createObjectURL( blob );
console.log($scope.url);
});
};
serverResponse.json
{"level":"info","message":"another-2fdas message"}
server.js
app.get('/file', function (req, res) {
var dir = './ditLogs';
var root = path.resolve('./ditLogs');
var fileName = req.query.file_name;
var data;
fs.readdir(dir, function(err, items) {
items.forEach(function(file){
if(fileName === file){
data = file;
res.setHeader('Content-Disposition', 'attachment; filename=' + data);
res.sendFile(data, {root: root});
}
});
});
});

If your are using express, you can try below code in server.js file:
var file = 'path to your file';
res.download(file,function(err){
if(!err){
console.log('prompted successfully');
return;
}
});

Related

using ng-file-upload to upload file from client to node and multer at node js to upload file on server, get req.file undefined always

I am using ng-file-upload to upload file from angular client to node js and at server side I am using multer to upload, Problem is I am not getting any error in multer but file is not uploaded, I found req.file is undefined always.Thanks in advance.
I am sharing my code:
view:
<form name="uploadform" role="upload" enctype="multipart/form-data" ng-submit="uploadFile();">
<input type="file" placeholder="Browse" class="btn btn-sm btn-
default" accept="application/pdf,application/msword,application/excel"
ngf-select="onFileSelect($files)">
</form>
myController:
$scope.onFileSelect = function($files) {
$scope.uploadfile = $files;
console.log("onFileSelect $scope.uploadfile is "+$scope.uploadfile);
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
console.log("$file name is "+$file.name);
console.log("$file type is "+$file.type);
console.dir("$file is "+$file);
}
}
//After click on upload button following method get called and fot that Upload here is ng-upload-file
$scope.uploadFile = function(){
Upload.upload({
url: hostname+'/upload',
//file:$scope.uploadfile[0], //webAPI exposed to upload the file
data:{file:$scope.uploadfile[0]} //pass file as data, should be user ng-model
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
//upload function returns a promise
if(data.data.error_code === 0){ //validate success
$window.alert('Success ' + data.config.data.file.name + 'uploaded. Response: ');
} else {
$window.alert('an error occured');
}
});
}
Routing:
router.post('/upload',upload1);
In app.js:
var multer = require('multer');
var storage = multer.diskStorage({ //multers disk storage settings
destination: function (req, file, cb) {
console.log("come inside storage destination"+" file is "+file);
cb(null, './uploads/')
},
filename: function (req, file, cb) {
var datetimestamp = Date.now();
console.log("come inside filename");
cb(null, file.fieldname + '-' + datetimestamp + '.' + file.originalname.split('.')[file.originalname.split('.').length -1])
}
});
var upload = multer({ //multer settings
storage: storage
}).single('file');*/
upload1: function(req, res) {
req.headers['content-type'] = 'multipart/form-data; boundary=something';
res.setHeader('Content-Type', 'applicaton/json');
/** API path that will upload the files */
console.dir("req is "+req);
req.headers['content-type'] = 'multipart/form-data; boundary=something';
res.setHeader('Content-Type', 'applicaton/json');
upload(req,res,function(err){
if(err){
res.json({error_code:1,err_desc:err});
return;
}
res.json({error_code:0,err_desc:null});
console.log("req.file" +req.file);
})
}
you should take the file as parameter in your function
$scope.uploadFile = function(file){
Upload.upload({
url: hostname+'/upload',
//file:$scope.uploadfile[0], //webAPI exposed to upload the file
data:{file:file} //pass file as data, should be user ng-model
}).then(function(data, status, headers, config) {
// file is uploaded successfully
console.log(data);
//upload function returns a promise
if(data.data.error_code === 0){ //validate success
$window.alert('Success ' + data.config.data.file.name + 'uploaded. Response: ');
} else {
$window.alert('an error occured');
}
});
}

How to parse an object sent from react frontend in express.js?

So in my react front-end, I am using the 'react-drop-to-upload' module to allow the user to drag a file and upload. I followed the example on the npm module page and created a handler called handleDrop. The code looks like:
handleDrop(files) {
var data = new FormData();
alert((files[0]) instanceof File);
files.forEach((file, index) => {
data.append('file' + index, file);
});
fetch('/file_upload', {
method: 'POST',
body: data
});
}
At my express backend, I have the following code:
app.post('/file_upload', function(req , res){
var body = '';
req.on('data', function (data) {
body += data;
});
var post = "";
req.on('end', function () {
//post = qs.parse(body);
console.log(body);
// this won't create a buffer for me
//var fileBuffer = new Buffer(body);
//console.log(fileBuffer.toString('ascii'));
//pdfText(body, function(err, chunks) {
//console.log(chunks);
//});
});
//console.log(typeof post);
});
If I drop a txt file and do a console log on the body, it would give me:
------WebKitFormBoundaryqlp9eomS0BxhFJkQ
Content-Disposition: form-data; name="file0"; filename="lec16.txt"
Content-Type: text/plain
The content of my data!
------WebKitFormBoundaryqlp9eomS0BxhFJkQ--
I am trying to use the pdfText module which takes in a buffer or a pathname to the pdf file, extract text from it into an array of text 'chunks' . I want to convert the body object into a buffer using var fileBuffer = new Buffer(body); but that won't work. Can someone help me with this? Thanks!
You need a parser for multi-part data. You can look into multer regarding that.
Example code for you,
app.post('/file_upload', function(req , res){
var storage = multer.diskStorage({
destination: tmpUploadsPath
});
var upload = multer({
storage: storage
}).any();
upload(req, res, function(err) {
if (err) {
console.log(err);
return res.end('Error');
} else {
console.log(req.body);
req.files.forEach(function(item) {
// console.log(item);
// do something with the item,
const data = fs.readFileSync(item.path);
console.log(data);
});
res.end('File uploaded');
}
});
});
To understand the example code in depth, head here. Remember, you will get the file data as a buffer and not as actual data.

How to upload my files to another server using multer in nodejs?

var storage = multer.diskStorage({
destination: function (req, file, callback) {
callback(null, '/var/www/html');
},
filename: function (req, file, callback) {
//console.log(file);return;
if (file.mimetype == 'audio/mp3' || file.mimetype == 'audio/wav') {
var w = file.originalname;
var f = x.substr(0, x.lastIndexOf('.'));
callback(null, Date.now()+'-'+w);
}else{
var result = new sResultSh.commandResult("Failed","404");
onComplete(result);
}
},
});
var upload = multer({ storage: storage}).any();
upload(req, res, function (err) {
if(err){
var resultErr =[];
resultErr.push(err);
var result = new sResultSh.commandResult("Failed","404",resultErr);
onComplete(result);
}
else{
var result = new sResultSh.commandResult("Success","200",);
onComplete(result);
}
})
Above is my code and i need to upload my file to 195.158.1.45/var/www/html..
How to do this in nodejs?
my file upload is successful in my local system but i need to upload my file to another server ?
help?
Uploading Files to remote server using multer is not possible directly, But we can play around with multer-sftp, scp, ssh techniques in node js
Check this answers using multer-sftp and scp2

How to upload file to s3 through nodejs express from Angularjs

I am facing problem to upload file to s3 by nodejs express, and angularjs.
I am using angular directive to send file to node express and from node to s3.
Angular directive :
(function() {
'use strict';
angular.module('app').directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.ngFileModel);
var isMultiple = attrs.multiple;
var modelSetter = model.assign;
element.bind('change', function () {
var values = [];
angular.forEach(element[0].files, function (item) {
var value = {
// File Name
name: item.name,
//File Size
size: item.size,
//File URL to view
url: URL.createObjectURL(item),
// File Input Value
_file: item
};
values.push(value);
});
scope.$apply(function () {
if (isMultiple) {
modelSetter(scope, values);
} else {
modelSetter(scope, values[0]);
}
});
});
}
};
}]);
})();
Html code
<input type="file" id="upme" ng-file-model="files" multiple style="display:none;" />
<div ng-if="files.length>0" ng-init="vm.uploadFile()"></div>
Server side:
exports.upload = function(req, res){
var images = req.body.images;
//res.send(images);
// console.dir(images)
images.forEach(function(file){
// console.dir(file);
S3.upFile('testbucket',file.name, file.url, function(err, data){
if(err){
console.log(err)
}else{
console.dir(data);
}
});
});
Problem,
The upload function works and I get something has been uploaded on s3 bucket, the file name appears in bucket; but it seems that is not actual size of the file and I can not open. when I click on the file url it say to download the file, after I download the file, it does not open. I think there may have any problem to parse the file in the node server before uploadin to s3. But I can't identify which solution should be there.
I also get one error in the console.
TypeError: path must be a string or Buffer
at TypeError (native)
at Object.fs.open (fs.js:625:11)
at ReadStream.open (fs.js:1708:6)
at new ReadStream (fs.js:1695:10)
at Object.fs.createReadStream (fs.js:1643:10)
I have made s3 file upload function as module in separate file. Here is module function of file upload
// uploading file or object into bucket
exports.upFile = function(bucket_name, key, file, next){
var params = {Bucket: bucket_name, Key: key, Body: fs.createReadStream(file), ACL:"public-read"};
s3.upload(params, function(err, data) {
next(err, data);
});
};
I appreciate any help from experts.
You are not giving a file as an argument to the upload function but an object URL. To correct your implementation, you have to make some changes in angular. Firstly, you should send files as multipart form data from angular. You can achieve this by using:
var form = new formData();
angular.forEach(element[0].files, function (item) {
form.append('file', item);
});
Send this form data to your node server using http request. You can define the route and http method using express in nodejs. On angularJS the request should look something like this:
$http.post('/test_route', form, {
withCredentials: false,
headers: {
'Content-Type': undefined
},
trnasformRequest: angular.identity
}).success(function(data) {
// do something with data from server
});
At node server, when you receive the request you have to extract files from form data. First define a route and method using express:
var multiparty = require('multiparty');
app.post('test_route', function(req, res) {
var form = new multiparty.Form();
form.parse(req, function(err, fields, files) {
var files_to_uplaod = files.file;
files_to_upload.forEach(function(file) {
read_file = fs.readFileSync(file.path);
var params = {Bucket: bucket_name, Key: file.originalFilename, Body: read_file, ACL:"public-read"};
s3.upload(params, function(err, data) {
next(err, data);
// once the file is uploaded you can remove the file from local disk which is saved whn multipart data arrives.
fs.unlink(file.path, function(err) {
if (err) {console.log(err);}
});
});
});
}
});
To parse the multiform on node server, use the multiparty module. More information can be found here: https://www.npmjs.com/package/multiparty

How to download a .docx file in AngularJs controller from Node.js

I've been looking in stackoverflow for some answer but I didn't succeed.
I have a node.js method in routes which generates a .docx template from another template with docxtemplater library.
I send a post from angularjs to my /api/generateReport with some data and I generate this .docx but I cant manage to send it.
It is not recommendable nor secure placing the file in /public dir but I can't download it if I place the file in /public dir and I provide the file path to AngularJs.
I've read about blob and other stuff but I can't manage to download a .docx file.
PS: I'm using $resource directive to handle api requests and I have set responseType to arrayBuffer
angular.module('MyApp')
.factory('GenerateReport', function($http, $location,$resource, $rootScope, $alert, $window) {
return $resource("/api/GenerateReport/:id",{}, {
'query': {
method: 'GET',
isArray: false
},
responseType: 'arrayBuffer'
});
});
I send the response this way.
var fileDocx = fs.readFileSync(__base + "/plantillaSalida.docx", "binary");
res.send(fileDocx);
Response is received in angular controller:
GenerateReport.save({
projectExecution: $scope.projectExecution,
auditingProject: $scope.auditingProject,
participants: $scope.participants,
exampleProjects: $scope.exampleProjects
}, function(response) {
/***What to to here??***/
$mdToast.show(
$mdToast.simple()
.content('Informe generado')
.position('bottom right left')
.hideDelay(3000)
);
},
function(error) {
console.log("error");
$mdToast.show(
$mdToast.simple()
.content('Error al general el informe')
.position('bottom right left')
.hideDelay(3000)
);
}
);
I would suggest to add download header to your file and link it using hyperlink (<a href="/download">)
var path = require('path');
var mime = require('mime');
app.get('/download', function(req, res){
var file = __base + "/plantillaSalida.docx";
var filename = path.basename(file);
var mimetype = mime.lookup(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.setHeader('Content-type', mimetype);
var filestream = fs.createReadStream(file);
filestream.pipe(res);
});
If you are using express use below code
app.get('/download', function(req, res){
var file = __base + "/plantillaSalida.docx";
var filename = path.basename(file);
res.setHeader('Content-disposition', 'attachment; filename=' + filename);
res.download(file);
});

Categories