I want to download a zip file and extract it with nodejs. This is what I have done so far:
var fs = require('fs');
var wget = require('wget-improved');
var filesizeHumanReadable = require('filesize');
var unzip = require('unzip');
var downloadCSS = function() {
var src = 'http://7-zip.org/a/7za920.zip';
var output = '/tmp/7z.zip';
var options = {};
var download = wget.download(src, output, options);
download.on('error', function(err) {
console.log(err);
});
download.on('start', function(fileSize) {
console.log(filesizeHumanReadable(fileSize));
});
download.on('end', function(outputMessage) {
console.log(outputMessage);
console.log(output);
fs.createReadStream(output).pipe(unzip.Extract({ path: '/tmp/' }));
});
download.on('progress', function(progress) {
// code to show progress bar
});
}
The error message I get when running it:
mles-MacBook-Pro:test-api mles$ node index.js
375.83 KB
Finished writing to disk
/tmp/7z.zip
events.js:85
throw er; // Unhandled 'error' event
^
Error: EPERM, unlink '/tmp'
at Error (native)
Now I'm a bit baffled how to handle the error event and what my actual error is?
Does the process have enough permission to write to /tmp? Does /tmp already have some files?
Because unlink is a node.js function to delete directories. Apparently, unzip.Extract calls it. So, unlink fails if the folder isn't empty (in your case /tmp).
Setting the unzip location to a specific directory fixes it
fs.createReadStream(output).pipe(unzip.Extract({ path: '/tmp/7zip' }));
I'm marking mostruash answer as correct since he brought me on the right track.
Related
I don't understand one thing with fs.rename(), why this code always throw an error?
The file is correctly renamed but each time i got this error Error: ENOENT: no such file or directory, rename '/path/to/file/example.log' -> '/path/to/file/example_1.log'
var fs = require('fs');
var mv = fs.rename('example.log', 'example_1.log', function(err) {
if(err instanceof Error)
throw err;
});
When I run your exact code:
var fs = require('fs');
var mv = fs.rename('example.log', 'example_1.log', function(err) {
if(err instanceof Error)
throw err;
});
(the only difference is adding the fs require).
Then I get the error when I don't have the file in the current directory.
But when I create example.log and run the program then I don't get any error and the file is renamed.
Of course next time I get the error again because I no longer have the file with the original name.
Are you sure that it doesn't work for you?
By the way, instead of
if (err instanceof Error)
you may want to use:
if (err)
Just in case that your error is not the instance of Error but still is defined (this can be true while using some modules).
I have a NodeJS script that I use to write JSON objects to file :
var reWriteCodes = function(arrayCodes, pathFileCodes, fs, typereWriteCodes, cb) {
console.log("message : "+ typereWriteCodes);
var codesStream = fs.createWriteStream(pathFileCodes, {'flags': 'w'});
codesStream.on('finish', () => {
console.log("the stream is closed")
if (typereWriteCodes === 0) {
cb();
}
});
var jsonToWrite = { "liste_codes" : arrayCodes};
codesStream.write(JSON.stringify(jsonToWrite));
codesStream.end();
}
This function is called twiced (first with typereWriteCodes = 0 then with typereWriteCodes = 1, inside the callback function : cb) with two different files.
The first call ends fine, my file is saved and the message "the stream is closed" displays in the console. But in the second call (which is the last operation of the program), my file is not saved correctly (the file is empty) and the message "the stream is closed" is not triggerd. Also, I get this message :
events.js:141
throw er; // Unhandled 'error' event
^
Error: ENOENT: no such file or directory, open ''
at Error (native)
I have the feeling that the app is closing before the stream could end correctly ... But I do not know how I can do this correctly. Could you help me with this issue ? Any help appreciated.
Im trying to compile a folder of markdown files into a single PDF with markdown-pdf NPM package.
I have a simple script to do the job:
var mpdf = require('markdown-pdf');
var fs = require('fs');
var mDocs = fs.readdirSync('./understandinges6/manuscript/');
mDocs = mDocs.map(function(d) { return 'understandinges6/manuscript/' + d });
var Book = 'understandinges6.pdf';
mpdf().concat.from(mDocs).to(Book, function() {
console.log("Created", Book);
});
But when i execute the script, this error appears:
events.js:154
throw er; // Unhandled 'error' event
^
Error: EISDIR: illegal operation on a directory, read
at Error (native)
It's weird because i'm in my home folder with the respective permissions. I'm specifying the output folder/file in the script and just reading with fs.readdirSync.
Any idea about this?
mDocs = mDocs.map(function(d) { return 'understandinges6/manuscript/' + d }); you forgot to add "./". Rewrite to mDocs = mDocs.map(function(d) { return './understandinges6/manuscript/' + d });
Cool, i get the problem here:
In the manuscripts/ folder are a images/ sub-folder with some png's. When the scripts tryed to read and transform images/ from .md to .pdf the error was fired.
Here is the array with the images/ inside:
[ 'understandinges6/manuscript/00-Introduction.md',
'understandinges6/manuscript/01-Block-Bindings.md',
'understandinges6/manuscript/02-Strings-and-Regular-Expressions.md',
'understandinges6/manuscript/03-Functions.md',
'understandinges6/manuscript/04-Objects.md',
'understandinges6/manuscript/05-Destructuring.md',
'understandinges6/manuscript/06-Symbols.md',
'understandinges6/manuscript/07-Sets-And-Maps.md',
'understandinges6/manuscript/08-Iterators-And-Generators.md',
'understandinges6/manuscript/09-Classes.md',
'understandinges6/manuscript/10-Arrays.md',
'understandinges6/manuscript/11-Promises.md',
'understandinges6/manuscript/12-Proxies-and-Reflection.md',
'understandinges6/manuscript/13-Modules.md',
'understandinges6/manuscript/A-Other-Changes.md',
'understandinges6/manuscript/B-ECMAScript-7.md',
'understandinges6/manuscript/Book.txt',
'understandinges6/manuscript/images' ]
Solution? Just pop() the mDocs array (now just docs):
var mpdf = require('markdown-pdf');
var fs = require('fs');
var mDocs = fs.readdirSync('understandinges6/manuscript/');
var docs = mDocs.map(function(d) { return 'understandinges6/manuscript/' + d });
docs.pop();
var Book = 'understandinges6.pdf';
mpdf().concat.from(docs).to(Book, function() {
console.log("Created", Book);
});
I am using NodeJS on heroku.
I read a file from another server and save it into my application in the /temp directory.
Next, I read the same file to pass it on to my client.
The code that saves the file and then subsequently reads it is:
http.request(options, function (pdfResponse) {
var filename = Math.random().toString(36).slice(2) + '.pdf',
filepath = nodePath.join(process.cwd(),'temp/' + filename);
pdfResponse.on('end', function () {
fs.readFile(filepath, function (err, contents) {
//Stuff to do after reading
});
});
//Read the response and save it directly into a file
pdfResponse.pipe(fs.createWriteStream(filepath));
});
This works well on my localhost.
However, when deployed to heroku, I get the following error:
events.js:72
throw er; // Unhandled 'error' event
Error: ENOENT, open '/app/temp/nvks0626yjf0qkt9.pdf'
Process exited with status 8
State changed from up to crashed
I am using process.cwd() to ensure that the path is correctly used. But even then it did not help. As per the heroku documentation, I am free to create files in the applications directory, which I am doing. But I can't figure out why this is failing to read the file...
The error you describe there is consistent with /app/temp/ not existing. You need to create it before you start writing in it. The idea is:
var fs = require("fs");
var path = require("path");
var temp_dir = path.join(process.cwd(), 'temp/');
if (!fs.existsSync(temp_dir))
fs.mkdirSync(temp_dir);
I've used the sync version of the calls for illustrations purposes only. This code should be part of the start up code for your app (instead of being called for each request) and how you should structure it depends on your specific application.
I made following, to play a bit around with node.js.
The files in the folder zipfiles are zipped accordingly and everything seems to work.
But I got an error on the cmd and I don't know where it comes from or how to solve it.
events.js:72
throw er; // Unhandled 'error' event
^
Error: write after end
at writeAfterEnd (_stream_writable.js:130:12)
at Gzip.Writable.write (_stream_writable.js:178:5)
at write (_stream_readable.js:583:24)
at flow (_stream_readable.js:592:7)
at ReadStream.pipeOnReadable (_stream_readable.js:624:5)
at ReadStream.EventEmitter.emit (events.js:92:17)
at emitReadable_ (_stream_readable.js:408:10)
at emitReadable (_stream_readable.js:404:5)
at readableAddChunk (_stream_readable.js:165:9)
at ReadStream.Readable.push (_stream_readable.js:127:10)
Here's my script:
var zlib = require('zlib');
var gzip = zlib.createGzip();
var fs = require('fs');
var zip = {
zipAll: function(dir){
//files to zip
fs.readdir(dir, function(err, data){
if(err) throw(err);
var arrayValue = data.toString().split(',');
//files with .gz at the end, needs to be excluded
for(var i=0; i<arrayValue.length; i+=1){
console.log("Zipping following files: " + arrayValue[i]);
var input = fs.createReadStream('zipfiles/' + arrayValue[i]);
var output = fs.createWriteStream('zipfiles/input'+[i]+'.txt'+'.gz');
input.pipe(gzip).pipe(output);
}
});
}
};
zip.zipAll('zipfiles');
Thanks
The Gzip object is a bit wonky (afaik undocumented) to reuse for multiple files. The easiest way to fix your problem is to simply use a separate gzip object per file to compress, something like;
for(var i=0; i<arrayValue.length; i+=1){
console.log("Zipping following files: " + arrayValue[i]);
var input = fs.createReadStream('zipfiles/' + arrayValue[i]);
var output = fs.createWriteStream('zipfiles/input'+[i]+'.txt'+'.gz');
input.pipe(zlib.createGzip()).pipe(output);
}