nodejs unzip with encoding option - node.js

I'm trying to make some code which makes server unzip requested file by using nodejs(express)...
app.post('/unzip', function(req, res) {
//Get User Information
var id = req.body.id;
//Get ZIP Information
var rendering_ready_file_unzip = req.body.filename + '.zip';
var rendering_ready_file_unzip_nonext = req.body.filename;
//Extract zip
var extract = require('extract-zip');
var unzip_route = path.join(__dirname, '../unzip/' + "id" + '/' + date + '/');;
extract(path.join(__dirname, '../upload/' + rendering_ready_file_unzip), {dir: unzip_route}, function (err) {
if (err) {
console.log(err);
}
res.end();
});}
It works... but other languages like Korean damaged after unzip.. So I want to know about unzip-modules which can designate encoding type.
Do you know it?

The problem may not be with the module. It helps to reduce troubled code to the minimum, and in this case that might be the following:
const path = require('path');
const extract = require('extract-zip');
const file_unzip = 'test.zip';
extract(path.join(__dirname, file_unzip), {dir: __dirname}, function (err) {
if (err) {
console.log(err);
}
});
After putting that in index.js and installing extract-unzip, a same-directory test case is possible in bash. Echo Korean characters to a file and make sure they are there:
$echo 안녕하세요>test
$cat test
안녕하세요
Zip the file, remove the original and make sure it is gone:
$zip test.zip test
adding: test (stored 0%)
$rm test
$ls test*
test.zip
Run the script and see that the file has been extracted and contains the same characters:
$node index.js
$ls test*
test test.zip
$cat test
안녕하세요
I got the same results with characters from several other languages. So at least in this setup, the module unzips without changing the characters in the inner files. Try running the same tests on your system, and take a good look at what happens prior to unzipping. Problems could lurk in how the files are generated, encoded, zipped, or uploaded. Investigate one step at a time.

Related

Unzip a MacOS .app file in Electron using Node.js

I am trying to unzip a file called Restart.Manager.zip which contains a single item, Restart Manager.app. This code seems to unzip the file correctly but upon launching the outputted .app folder, I get an error "The application “Restart Manager” can’t be opened."
const JSZip = require('jszip');
const fs = require('fs');
const jetpack = require('fs-jetpack');
const originalFs = require('original-fs');
async function extractZip(filePath, destination) {
fs.readFile(filePath, function(err, data) {
if (!err) {
var zip = new JSZip();
zip.loadAsync(data).then(function(contents) {
Object.keys(contents.files).forEach(function(filename) {
const file = zip.file(filename);
if (file) {
file.async('nodebuffer').then(function(content) {
var dest = destination + '/' + filename;
if (filename.endsWith('.asar')) {
originalFs.writeFileSync(dest, content)
} else {
jetpack.write(dest, content);
}
});
}
});
});
}
});
};
extractZip('/Users/me/Desktop/Restart.Manager.zip', '/Users/me/Desktop')
Manually unzipping the .zip file creates a working .app so I'm not sure where the code is messing up.
Here is the file on GitHub releases for testing: https://github.com/itw-creative-works/restart-manager-download-server/releases/download/installer/Restart.Manager.zip but feel free to use your own zipped .app file (although it should probably be an Electron app in which case you can find one here https://www.electronjs.org/apps)
I have tried zipping things like a .png and it unzips fine, which makes me think it is having problems with .app files or possibly the fact that the .app contains a .asar file which Electron supposedly has problems handling when it comes to the fs module: https://github.com/electron/electron/issues/1658

Switch to what ever path is input nodejs

Lets assume you have installed an electron app and you are asked to input the path to your current project. You might do something like: ~/Documents/projectName.
How do I, in node take that input and check if it exists, specifically if you entered in the path as shown above?
the reason for this is that I want to see if A) the path exists and B) if theres a specific file there (I'll be using path.join(dirEntered, fileName.extension).
Is there a way to do what I want? I see chdir but that changes where the working directory is. which I guess would be fine but doing:
process.chdir('~/Documents') Shows: no such file or directory, uv_chdir(…)
I want to avoid having the user to enter the full absolute path of their project. That seems "bad to me". And uploading their project isn't necessary, Im reading a single file (so theres no need for upload here).
Any ideas?
Is it possible to tap into the cli commands and take this input feed it there and get the result? Or is that over kill?
Here's an idea how to solve it. If the path starts with a tilde, it replaces that tilde with the full home directory of the current user. It then uses fs.stat to see if the given path actually exists.
const fs = require("fs");
const os = require("os");
var path = "~/Documents";
if (path.indexOf("~") === 0) {
path = os.homedir() + path.substring(1);
}
fs.stat(path, (err, stats) => {
if (!err) {
// document or path exists
if (stats.isFile()) {
console.log("Path " + path + " is a file");
} else if (stats.isDirectory()) {
console.log("Path " + path + " is a directory");
}
} else {
// document or path does not exist
}
});

nodejs written file is empty

i have a small problem, when i try to copy one file from my tmp dir to my ftp dir the writen file is empty. I have no error, i don't understand what i'm doing wrong
var ftpPath = "/var/www/ftp/",
zipPath = "/var/www/tmp/",
file = "test";
fs.createReadStream(zipPath + file).pipe(fs.createWriteStream(ftpPath + file));
My test file contain loremipsum sample.
If you have any solution, i take it, this is the only line that bug in my app :(
First, make sure that the file /var/www/tmp/test exists, is a file, and has the right permissions for the user you start the script with.
Second, make sure that /var/www/ftp/ has writing permissions.
Then the following code should work :
var readerStream = fs.createReadStream('/var/www/tmp/test');
var writerStream = fs.createWriteStream('/var/www/ftp/test');
readerStream.pipe(writerStream);
Edit :
try debugging using this snippet :
var data;
var readerStream = fs.createReadStream('/var/www/tmp/test');
readerStream.on('data', function(data) {
data += data;
});
readerStream.on('end', function() {
console.log(data);
});

how to use NodeJS to modify a file and save to a new one?

I have a plain text file named source.txt
I want to use a NodeJS script to do something to modify the content of the txt file and save as a new file, say output.txt
How do I do that?
I am expecting a command-line implementation, something like:
$node modify.js source.txt output.txt
Thanks!
Sync style:
// save as: uppercase.js
var fs = require('fs');
var input = process.argv[2];
var output = process.argv[3];
var content = fs.readFileSync(input, 'utf8');
content = content.toUpperCase();
fs.writeFileSync(output, content);
Run:
$node uppercase source.txt output.txt
Use Node.js's build in fs() function to read and write files to the local filesystem.
Basic read example:
fs.readFile('source.txt', function (err, data) {
if (err) throw err;
console.log(data);
});
Basic write example:
fs.writeFile('output.txt', 'Hello Node', function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
Note: ensure your Node instance (and the account it's being run under) has appropriate permissions to the read and write source/destination.

Meteor/Node writeFile crashes server

I have the following code:
Meteor.methods({
saveFile: function(blob, name, path, encoding) {
var path = cleanPath(path), fs = __meteor_bootstrap__.require('fs'),
name = cleanName(name || 'file'), encoding = encoding || 'binary',
chroot = Meteor.chroot || 'public';
// Clean up the path. Remove any initial and final '/' -we prefix them-,
// any sort of attempt to go to the parent directory '..' and any empty directories in
// between '/////' - which may happen after removing '..'
path = chroot + (path ? '/' + path + '/' : '/');
// TODO Add file existance checks, etc...
fs.writeFile(path + name, blob, encoding, function(err) {
if (err) {
throw (new Meteor.Error(500, 'Failed to save file.', err));
} else {
console.log('The file ' + name + ' (' + encoding + ') was saved to ' + path);
}
});
function cleanPath(str) {
if (str) {
return str.replace(/\.\./g,'').replace(/\/+/g,'').
replace(/^\/+/,'').replace(/\/+$/,'');
}
}
function cleanName(str) {
return str.replace(/\.\./g,'').replace(/\//g,'');
}
}
});
Which I took from this project
https://gist.github.com/dariocravero/3922137
The code works fine, and it saves the file, however it repeats the call several time and each time it causes meteor to reset using windows version 0.5.4. The F12 console ends up looking like this: . The meteor console loops over the startup code each time the 503 happens and repeats the console logs in the saveFile function.
Furthermore in the target directory the image thumbnail keeps displaying and then display as broken, then a valid thumbnail again, as if the fs is writing it multiple times.
Here is the code that calls the function:
"click .savePhoto":function(e, template){
e.preventDefault();
var MAX_WIDTH = 400;
var MAX_HEIGHT = 300;
var id = e.srcElement.id;
var item = Session.get("employeeItem");
var file = template.find('input[name='+id+']').files[0];
// $(template).append("Loading...");
var dataURL = '/.bgimages/'+file.name;
Meteor.saveFile(file, file.name, "/.bgimages/", function(){
if(id=="goodPhoto"){
EmployeeCollection.update(item._id, { $set: { good_photo: dataURL }});
}else{
EmployeeCollection.update(item._id, { $set: { bad_photo: dataURL }});
}
// Update an image on the page with the data
$(template.find('img.'+id)).delay(1000).attr('src', dataURL);
});
},
What's causing the server to reset?
My guess would be that since Meteor has a built-in "automatic directories scanning in search for file changes", in order to implement auto relaunching of the application to newest code-base, the file you are creating is actually causing the server reset.
Meteor doesn't scan directories beginning with a dot (so called "hidden" directories) such as .git for example, so you could use this behaviour to your advantage by setting the path of your files to a .directory of your own.
You should also consider using writeFileSync insofar as Meteor methods are intended to run synchronously (inside node fibers) contrary to the usual node way of asynchronous calls, in this code it's no big deal but for example you couldn't use any Meteor mechanics inside the writeFile callback.
asynchronousCall(function(error,result){
if(error){
// handle error
}
else{
// do something with result
Collection.update(id,result);// error ! Meteor code must run inside fiber
}
});
var result=synchronousCall();
Collection.update(id,result);// good to go !
Of course there is a way to turn any asynchronous call inside a synchronous one using fibers/future, but that's beyond the point of this question : I recommend reading this EventedMind episode on node future to understand this specific area.

Resources