I do not know if this is possible, but here goes. And working with callbacks makes it even more difficult.
I have a directory with html files that I want to send back to the client in Object chunks with node.js and socket.io.
All my files are in /tmpl
So socket needs to read all the files in /tmpl.
for each file it has to store the data in an object with the filename as the key, and the content as the value.
var data; // this is wrong because it has to loop trough all files. fs.readFile(__dirname + '/tmpl/filename.html', 'utf8', function(err, html){ if(err) throw err; //filename must be without .html at the end data['filename'] = html; }); socket.emit('init', {data: data});
The final callback is also wrong. It has to be called when all the files in the directory are done.
But I do not know how to create the code, anyone know if this is possibel?
To get a list of all the files and folders in a particular directory in the filesystem, use os. listdir() in legacy versions of Python or os. scandir() in Python 3.
readdir() method is used to asynchronously read the contents of a given directory. The callback of this method returns an array of all the file names in the directory. The options argument can be used to change the format in which the files are returned from the method.
So, there are three parts. Reading, storing and sending.
Here's the reading part:
var fs = require('fs'); function readFiles(dirname, onFileContent, onError) { fs.readdir(dirname, function(err, filenames) { if (err) { onError(err); return; } filenames.forEach(function(filename) { fs.readFile(dirname + filename, 'utf-8', function(err, content) { if (err) { onError(err); return; } onFileContent(filename, content); }); }); }); }
Here's the storing part:
var data = {}; readFiles('dirname/', function(filename, content) { data[filename] = content; }, function(err) { throw err; });
The sending part is up to you. You may want to send them one by one or after reading completion.
If you want to send files after reading completion you should either use sync versions of fs
functions or use promises. Async callbacks is not a good style.
Additionally you asked about stripping an extension. You should proceed with questions one by one. Nobody will write a complete solution just for you.
This is a modern Promise
version of the previous one, using a Promise.all
approach to resolve all promises when all files have been read:
/** * Promise all * @author Loreto Parisi (loretoparisi at gmail dot com) */ function promiseAllP(items, block) { var promises = []; items.forEach(function(item,index) { promises.push( function(item,i) { return new Promise(function(resolve, reject) { return block.apply(this,[item,index,resolve,reject]); }); }(item,index)) }); return Promise.all(promises); } //promiseAll /** * read files * @param dirname string * @return Promise * @author Loreto Parisi (loretoparisi at gmail dot com) * @see http://stackoverflow.com/questions/10049557/reading-all-files-in-a-directory-store-them-in-objects-and-send-the-object */ function readFiles(dirname) { return new Promise((resolve, reject) => { fs.readdir(dirname, function(err, filenames) { if (err) return reject(err); promiseAllP(filenames, (filename,index,resolve,reject) => { fs.readFile(path.resolve(dirname, filename), 'utf-8', function(err, content) { if (err) return reject(err); return resolve({filename: filename, contents: content}); }); }) .then(results => { return resolve(results); }) .catch(error => { return reject(error); }); }); }); }
How to Use It:
Just as simple as doing:
readFiles( EMAIL_ROOT + '/' + folder) .then(files => { console.log( "loaded ", files.length ); files.forEach( (item, index) => { console.log( "item",index, "size ", item.contents.length); }); }) .catch( error => { console.log( error ); });
Supposed that you have another list of folders you can as well iterate over this list, since the internal promise.all will resolve each of then asynchronously:
var folders=['spam','ham']; folders.forEach( folder => { readFiles( EMAIL_ROOT + '/' + folder) .then(files => { console.log( "loaded ", files.length ); files.forEach( (item, index) => { console.log( "item",index, "size ", item.contents.length); }); }) .catch( error => { console.log( error ); }); });
How it Works
The promiseAll
does the magic. It takes a function block of signature function(item,index,resolve,reject)
, where item
is the current item in the array, index
its position in the array, and resolve
and reject
the Promise
callback functions. Each promise will be pushed in a array at the current index
and with the current item
as arguments through a anonymous function call:
promises.push( function(item,i) { return new Promise(function(resolve, reject) { return block.apply(this,[item,index,resolve,reject]); }); }(item,index))
Then all promises will be resolved:
return Promise.all(promises);
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