Node js App to display folder files - node.js

I am trying to display file list from folders .
my folder structure is like below
Invoices
1. error
2. processed
3. unprocessed
I have created node api for same which i am calling on my html page. code for the same is as below
const fs = require('fs');
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
app.use(express.static(__dirname));
var flength;
var filename;
var currentFile;
var items = [];
var dir1 = 'Invoices';
var filepath = [];
var readFolder = function(dir1) {
var countt = function(filename) {
var currentFile = dir1 + '/' + filename;
fs.readdir(currentFile, (err, files) => {
flength = files.length;
var fileArrayList = [];
for (var f in files) {
var record = {
filename: files[f],
filepath: dir1 + '/' + filename + '/' + files[f]
}
fileArrayList.push(record);
}
items.push({
'file': filename,
'count': flength,
'files': fileArrayList
});
});
}
var ReadFirst = function(dir1) {
fs.readdir(dir1, (err, files) => {
for (var i in files) {
var filename = files[i];
var currentFile = dir1 + '/' + filename;
var stats = fs.statSync(currentFile);
if (stats.isDirectory()) {
countt(filename);
}
}
});
}
ReadFirst(dir1);
}
setTimeout(function(str1, str2) {
readFolder(dir1);
}, 1000);
app.get('/FileCount', function(req, res) {
res.send(items);
});
app.listen(4000);
console.log('Listening on port 4000');
When i add or delete files from any folder then its not reflecting on my html page.need help for this.
thank you.

This is happening because of the way you've implemented this.
Your client (the HTML page) requests the server (NodeJS) API for
some data. In this case, it is the list of files in a folder. The server sends the response based on the state of files at the time (plus ∆).
You display those results in the HTML page. Now, there is no live link between your HTML page and your backend server. This means any changes that happen after this point won't be automatically reflected in the page.
You can do two things here:
Call your API repeatedly after an interval of few seconds. (If you're using AngularJS, look into setTimeout function.
Use sockets for having a real-time link. One good documentation here:
https://loopback.io/doc/en/lb2/Realtime-socket-io.html
This is more of a design issue and your NodeJS API looks fine.

Related

Restify JsonClient URL x Path

When I create a JsonClient in node I do the following:
var client = restify.createJsonClient({
url: 'https://www.domain.com:4321/api'
});
Once I've done that, I make calls like so:
client.post('/service/path', { });
Which seems right. I expect that the path called would be something like https://www.domain.com:4321/api/service/path. However, what is happening is that the client is throwing away the /api base path and calling https://www.domain.com:4321/service/path.
I don't get it - I'm inserting the client URL into a config file, so that I can change hosts without any hassle; Now that I need a base path, I need to change the code as well as the config.
If you put a wrapper around the restify JsonClient stuff you could do it with minimal code change and the config would, I think, work the way you want it.
Create a library file myClient.js
'use strict';
var restify = require('restify');
var jsonClient = null;
module.exports = {
createJsonClient: function(opts){
var opts = opts || {};
var url = opts.url;
var parts = url.split('/');
var main_url = parts[0] + '//' + parts[2];
var basePath = parts[3] ? parts[3] : '';
jsonClient = restify.createJsonClient({url: main_url});
return {
get: function(path, cb){
var adjusted_path = '/' + basePath + path;
jsonClient.get(adjusted_path, function(err2, req2, res2, obj2){
return cb(err2, req2, res2, obj2);
});
}
}
}
}
Then use it like this.
var myClientWrapper = require('./lib/myClient');
var client = myClientWrapper.createJsonClient({url: 'http://localhost:8000/api'});
client.get('/service/path/one', function(err, req, res, obj){
if(err){
console.log(err.message);
return;
}
console.log(res.body);
});
It could use some more error checking and the url parsing is a little brittle, but it does work. I tried it out. Of course, I only wrapped the get function but you can see how it would work for the others.

image upload with "post" in nodejs with request module

How do we upload an image received form the mobile app to another server using the request module in nodejs?
I have tried using the multipart module to extract the file and send it in formData attribute with the request module (post method). This doesn't seem to work.
Please Use following code, it has been tested in express. you can modify it according to your requirement
var path = require('path');
var util = require('util');
if (req.files.profile_image !== undefined) {
var file = req.files.profile_image;
var tmp_path = file.path;
var fileName = file.name;
var milliseconds = new Date().getTime();
var file_ext = fileName.substr((Math.max(0, fileName.lastIndexOf(".")) || Infinity) + 1);
var newFileName = requestedUser + '_' + milliseconds + '.' + file_ext;
var pathToFile = require('path').dirname(require.main.filename);
var mainPath = path.dirname(pathToFile)
var target_path = path.join(mainPath, 'public/uploads/users', newFileName);
var readStream = fs.createReadStream(tmp_path)
var writeStream = fs.createWriteStream(target_path);
util.pump(readStream, writeStream, function(err) {
if (err) {
//handle error
} else {
//successfully uploaded
}
});
} else {
//file not recieved
}
Thanks

How to concurrent download files using cheerio and nodejs?

I have a website with multiple pages, each page lists download links which I want to scrap and download.
I have few issues with it:
My script only downloads about 4-5 files and getting stuck.
I would like to concurrently download as much files as my CPU can.
I got stuck with maximum event emitters, I don't understand why is that so I just go
How to follow redirects purely using request module (without follow-redirects)?
How to download the file like the browser does without mentioning it's name? there is no content-disposition but I think the browser follow redirects and the redirected URL has the filename in it's path.
My current code looks like so:
var request = require('request');
var cheerio = require('cheerio');
var https = require('follow-redirects').https;
require('events').EventEmitter.prototype._maxListeners = 1000;
for(var i = 1; i <= 10000; i++) {
(function(i){
url = 'http://mywebsite.com/files?page=' + i;
request(url, gotHTML)
})(i);
}
function gotHTML(err, resp, html) {
var $ = cheerio.load(html);
$('.file-header').each(function() {
var data = $(this);
var fileLink = data.children().first().children().first().attr('href');
var fileName = fileLink.substring(10);
var downloadLink = 'https://mywebsite.com/api/download/' + fileName;
download(downloadLink, function() {
console.log('downloaded');
})
})
}
function download(url, cb) {
var request = https.get(url, function(response) {
var location = request.res.headers.location;
console.log(location);
location = location.split('/').pop();
console.log(location);
var file = fs.createWriteStream(location);
response.pipe(file);
file.on('finish', function() {
file.close(cb);
});
});
}
The default HTTP/HTTPS Agent only uses a maximum of 5 sockets (maxSockets) for requests to the same origin. So this could be causing some issues for you.
Try changing this:
var request = https.get(url, function(response) {
to this:
var options = require('url').parse(url);
options.agent = false; // or use a custom https.Agent with a higher `maxSockets`
var request = https.get(options, function(response) {

File Upload in KoaJS

I'm trying to upload files using the code from example. But it's not working.
In the controller I wrote the code
var parse = require('co-busboy');
var fs = require('fs');
var path = require('path');
var parts = parse(this);
var part;
while (part = yield parts) {
var stream = fs.createWriteStream('/tmp/' + part.filename);
part.pipe(stream);
console.log('uploading %s -> %s', part.filename, stream.path);
}
But when I upload images in the console I only get new uploading location. But on new location images are not saving.
Any Solution?
Thanks in Advance,
Nixon
I got the answer. I just had to remove '/' before the 'tmp'.
So the code is like this
while (part = yield parts) {
var stream = fs.createWriteStream('tmp/' + part.filename);
part.pipe(stream);
console.log('uploading %s -> %s', part.filename, stream.path);
}

Send PDF file from AngularJS to NodeJS

i need to send a PDF file from angularjs client to NodeJS service.
I did the angularjs service, and when i receive the file its a string like this:
%PDF-1.3
3 0 obj
<</Type /Page
/Parent 1 0 R
/Reso
How can i reconvert this string to PDF in NodeJS?
This is the client code:
var sendByEmail = function () {
$scope.generatingPdf = true;
$('#budget').show();
var pdf = new JsPDF('p', 'pt', 'letter');
var source = $('#budget')[0];
pdf.addHTML(source, 0, 0, function () {
var resultPdf = pdf.output();
BillService.sendByEmail("rbrlnx#gmail.com", resultPdf).then(function () {
});
$('#budget').hide();
});
};
var sendByEmail = function (email, file) {
var deferred = $q.defer();
var data = {
email: email,
file: file
};
BillService.sendByEmail(data, function (result) {
deferred.resolve(result);
}, function () {
deferred.reject();
});
return deferred.promise;
};
The server code controller its empty:
var sendByEmail = function (req, res, next) {
var file = req.body.file;
};
I experimented with this a while ago, and I came up with this. It's not production ready by a long shot maybe you find it useful. It's free of front end libraries (except Angular ofcourse), but assumes you're using Express 4x and body-parser.
The result:
In the browser:
On the server:
What you're seeing:
You're seeing a tiny node server, serving static index.html and angular files, and a POST route receiving a PDF in base64 as delivered by the HTML FileReader API, and saves it to disk.
Instead of saving to disk, you can send it as an email attachment. See for instance here or here for some info on that.
The example below assumes uploading a PDF by a user through a file input, but the idea is the same for all other ways of sending a document to your back end system. The most important thing is to send the pdf data as BASE64, because this is the format that most file writers and email packages use (as opposed to straight up binary for instance..). This also goes for images, documents etc.
How did I do that:
In your HTML:
<div pdfs>Your browser doesn't support File API.</div>
A directive called pdfs:
myApp.directive('pdfs', ['upload', function(upload) {
return {
replace: true,
scope: function() {
files = null;
},
template: '<input id="files" type="file">',
link: function(scope,element) {
element.bind('change', function(evt) {
scope.$apply(function() {
scope.files = evt.target.files;
});
});
},
controller: function($scope, $attrs) {
$scope.$watch('files', function(files) {
//upload.put(files)
if(typeof files !== 'undefined' && files.length > 0) {
for(var i = 0; i<files.length;i++) {
readFile(files[i])
}
}
}, true);
function readFile(file) {
var reader = new FileReader();
reader.addEventListener("loadend", function(evt) {
upload.post({name: file.name, data: reader.result})
})
if(reader.type = 'application/pdf') {
reader.readAsDataURL(file);
}
}
}
}
}]);
A tiny service:
myApp.service('upload', function($http) {
this.post = function(file) {
$http.post('/pdf', file);
}
});
And a node server:
var express = require('express');
var bodyParser = require('body-parser')
var fs = require("fs");
var app = express();
app.use(express.static('.'));
app.use( bodyParser.json({limit: '1mb'}) );
app.post('/pdf', function(req, res){
var name = req.body.name;
var pdf = req.body.data;
var pdf = pdf.replace('data:application/pdf;base64,', '');
res.send('received');
fs.writeFile(name, pdf, 'base64', function(err) {
console.log(err);
});
});
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
});

Resources