用于tar文件的Node.js-exec命令第一次可以正常工作,但在后续执行时会产生损坏的tar内容
我正在用Node.js构建一个web应用程序,现在我需要生成PDF目录的tar存档。该应用程序运行在运行Ubuntu 14.04服务器的VM上。我的代码如下所示:用于tar文件的Node.js-exec命令第一次可以正常工作,但在后续执行时会产生损坏的tar内容,node.js,linux,tar,Node.js,Linux,Tar,我正在用Node.js构建一个web应用程序,现在我需要生成PDF目录的tar存档。该应用程序运行在运行Ubuntu 14.04服务器的VM上。我的代码如下所示: function tarDirectory(path, token, callback) { var exec = require('child_process').exec; var cmd = 'cd ' + path + ' && tar -cvf genericName-' + token + '.ta
function tarDirectory(path, token, callback) {
var exec = require('child_process').exec;
var cmd = 'cd ' + path + ' && tar -cvf genericName-' + token + '.tar' + ' ' + token;
exec(cmd, function(error, stdout, stderr) {
console.log(stdout);
console.log(stderr);
if (error) {
console.error(error);
}
if(callback) callback();
});
}
此tarDirectory函数由以下代码调用:
router.post('/files/generate', function(req, res, next) {
IDList = req.body['IDs[]'];
token = req.body['token'];
// if just a single file being generated
if (typeof req.body['IDs[]'] === "string"){
filehelper.generateFile(IDList[0], req.app.locals.site.basedir + "temp/", token);
}
// if multiple files being generated
else {
IDList.forEach(function(id) {
filehelper.generateFile(id, req.app.locals.site.basedir + "temp/", token);
});
}
filehelper.tarDirectory(req.app.locals.site.basedir + "temp/", token, res.end);
});
代码需要一个post请求,该请求包含通过在我的web应用程序中单击按钮生成的动态数据,然后将基于该数据创建文件并将其放入目录中。这一切都很好。。。第一次。当我在一段时间内第一次单击该按钮时,会生成tar,当我打开它时,客户端PDF与服务器上的PDF完全相同。不过,当我在一个小时左右再次单击时,我会收到一个tar文件,但当我打开归档文件并将其解压缩时,PDF文件都已损坏,大约是预期字节大小的一半。我在这里不知所措。。。我怀疑这可能与流关闭的不当处理有关,但我不确定
这是将PDF生成到目录中的代码,该目录在生成后会涂上焦油:
function generateFile(id, path, token) {
var dirPath = path + token;
var filePath = path + token + "/file" + id + ".pdf";
console.log("creating file for: " + id);
try{
fs.statSync(dirPath).isDirectory();
} catch (err) {
fs.mkdirSync(dirPath);
}
// start the file pdf generation
file = new PDFDocument();
output = fs.createWriteStream(filePath);
output.on('close', function(){
return;
});
file.pipe(output);
// handle the intricacies of the file generation
file.text("file" + id + ".pdf");
// end the file
file.end();
}
generateFile
函数中,您有WriteStream,它是异步的。但是,您将此函数称为sync.,并在pdf生成完成之前启动.tar压缩,这可能会导致此问题generateFile
,或迭代异步,并仅在所有文件生成完成后才开始压缩var Promise = require('bluebird');
function generateFile(id, path, token) {
return new Promise(function(resolve, reject) {
var dirPath = path + token;
var filePath = path + token + "/file" + id + ".pdf";
console.log("creating file for: " + id);
try{
fs.statSync(dirPath).isDirectory();
} catch (err) {
fs.mkdirSync(dirPath);
}
// start the file pdf generation
file = new PDFDocument();
output = fs.createWriteStream(filePath);
output.on('close', function(){
return resolve();
});
output.on('error', function(error) {
return reject(error);
});
file.pipe(output);
// handle the intricacies of the file generation
file.text("file" + id + ".pdf");
// end the file
file.end();
});
}
PDF生成和压缩
var Promise = require('bluebird');
....
//IDList.forEach(function(id) {
// filehelper.generateFile(id, req.app.locals.site.basedir + "temp/", //token);});
//replace with
Promise.map(IDList, function(id) {
return filehelper.generateFile(id, req.app.locals.site.basedir + "temp/", token);
})
.then(function() {
//all files are ready, start compressing
})
.catch(function(error) {
//we have error
});
generateFile
函数中,您有WriteStream,它是异步的。但是,您将此函数称为sync.,并在pdf生成完成之前启动.tar压缩,这可能会导致此问题generateFile
,或迭代异步,并仅在所有文件生成完成后才开始压缩var Promise = require('bluebird');
function generateFile(id, path, token) {
return new Promise(function(resolve, reject) {
var dirPath = path + token;
var filePath = path + token + "/file" + id + ".pdf";
console.log("creating file for: " + id);
try{
fs.statSync(dirPath).isDirectory();
} catch (err) {
fs.mkdirSync(dirPath);
}
// start the file pdf generation
file = new PDFDocument();
output = fs.createWriteStream(filePath);
output.on('close', function(){
return resolve();
});
output.on('error', function(error) {
return reject(error);
});
file.pipe(output);
// handle the intricacies of the file generation
file.text("file" + id + ".pdf");
// end the file
file.end();
});
}
PDF生成和压缩
var Promise = require('bluebird');
....
//IDList.forEach(function(id) {
// filehelper.generateFile(id, req.app.locals.site.basedir + "temp/", //token);});
//replace with
Promise.map(IDList, function(id) {
return filehelper.generateFile(id, req.app.locals.site.basedir + "temp/", token);
})
.then(function() {
//all files are ready, start compressing
})
.catch(function(error) {
//we have error
});
所以我实现了纳扎尔提出的承诺。如果我只生成一个文件,那么整个操作现在可以正常工作,但是如果生成更多文件,则会得到相同的损坏PDF 生成单个文件的代码:
function generateFile(id, path, token) {
return new Promise(function(resolve, reject){
var dirPath = path + token;
var filePath = path + token + "/file" + id + ".pdf";
console.log("creating file for: " + id);
try{
fs.statSync(dirPath).isDirectory();
} catch (err) {
fs.mkdirSync(dirPath);
}
// start the file pdf generation
file = new PDFDocument();
output = fs.createWriteStream(filePath);
// stream handling
output.on('finish', function(){
console.log(fs.statSync(filePath)["size"]);
return resolve();
});
output.on('error', function(error) {
return reject(error);
});
// pipe the generated PDF to the output file
file.pipe(output);
// handle the intricacies of the transcript generation
file.text("file" + id + ".pdf");
// end the file
file.end();
});
}
我的目录tar代码:
function tarDirectory(path, token) {
return new Promise(function(resolve, reject){
var exec = require('child_process').exec;
var cmd = 'cd ' + path + ' && tar -cvf Files-' + token + '.tar' + ' ' + token;
exec(cmd, function(error, stdout, stderr) {
if (stdout != "") console.log(stdout);
if (stderr != "") console.log(stderr);
if (error) return reject(error);
return resolve();
});
});
}
以及我调用两个helper函数的代码:
// submit request to generate files
router.post('/files/generate', function(req, res, next) {
IDList = req.body['IDs[]'];
token = req.body['token'];
// convert single fileID into list because Promise.map() needs iterable
if (typeof IDList === "string") {
IDList = [IDList];
}
Promise.map(IDList, function(id) {
filehelper.generateFile(id, req.app.locals.site.basedir + "temp/", token);
})
.then(function() {
return filehelper.tarDirectory(req.app.locals.site.basedir + "temp/", token);
})
.then(function() {
res.end();
})
.catch(function(error) {
throw new Error('Something went wrong while generating the tar file! :(\n' + error);
});
});
对于我在这里可能犯下的错误的任何进一步见解,我都非常感激。因此我实现了纳扎尔提出的承诺。如果我只生成一个文件,那么整个操作现在可以正常工作,但是如果生成更多文件,则会得到相同的损坏PDF 生成单个文件的代码:
function generateFile(id, path, token) {
return new Promise(function(resolve, reject){
var dirPath = path + token;
var filePath = path + token + "/file" + id + ".pdf";
console.log("creating file for: " + id);
try{
fs.statSync(dirPath).isDirectory();
} catch (err) {
fs.mkdirSync(dirPath);
}
// start the file pdf generation
file = new PDFDocument();
output = fs.createWriteStream(filePath);
// stream handling
output.on('finish', function(){
console.log(fs.statSync(filePath)["size"]);
return resolve();
});
output.on('error', function(error) {
return reject(error);
});
// pipe the generated PDF to the output file
file.pipe(output);
// handle the intricacies of the transcript generation
file.text("file" + id + ".pdf");
// end the file
file.end();
});
}
我的目录tar代码:
function tarDirectory(path, token) {
return new Promise(function(resolve, reject){
var exec = require('child_process').exec;
var cmd = 'cd ' + path + ' && tar -cvf Files-' + token + '.tar' + ' ' + token;
exec(cmd, function(error, stdout, stderr) {
if (stdout != "") console.log(stdout);
if (stderr != "") console.log(stderr);
if (error) return reject(error);
return resolve();
});
});
}
以及我调用两个helper函数的代码:
// submit request to generate files
router.post('/files/generate', function(req, res, next) {
IDList = req.body['IDs[]'];
token = req.body['token'];
// convert single fileID into list because Promise.map() needs iterable
if (typeof IDList === "string") {
IDList = [IDList];
}
Promise.map(IDList, function(id) {
filehelper.generateFile(id, req.app.locals.site.basedir + "temp/", token);
})
.then(function() {
return filehelper.tarDirectory(req.app.locals.site.basedir + "temp/", token);
})
.then(function() {
res.end();
})
.catch(function(error) {
throw new Error('Something went wrong while generating the tar file! :(\n' + error);
});
});
如果您能进一步了解我在这里可能犯的错误,我们将不胜感激。1。是的,PDF在服务器上的原始文件夹中完好无损,因此它们肯定是正确生成的。2.我认为这是在正确的轨道上。。。我将考虑为此使用承诺。3.感谢您提供的示例:)因此,在实施您的承诺建议后,我能够让它正确地生成PDF,如果它一次只生成一个PDF。调查。。。我会回复你的。是的,PDF在服务器上的原始文件夹中完好无损,因此它们肯定是正确生成的。2.我认为这是在正确的轨道上。。。我将考虑为此使用承诺。3.感谢您提供的示例:)因此,在实施您的承诺建议后,我能够让它正确地生成PDF,如果它一次只生成一个PDF。调查。。。将返回给您执行下一步操作:
function generateFile
,将resolve()
替换为resolve({id:id,path:filePath})
。在Promise.map
-首先。然后(function()
)与一起,然后(function(files)
。打印此文件,以验证名称是否正确。没有足够的信息。我认为您试图写入同一个文件。我解决了此问题。这是因为我没有返回promise.map()中生成的承诺.Nazar.为您的帮助干杯。执行下一步:function generateFile
,将resolve()
替换为resolve({id:id,path:filePath})
。并在Promise.map中,首先将映射为,然后将替换为
,然后再替换为函数(文件)
。打印此文件,以验证名称是否正确。没有足够的信息。我认为您试图写入同一个文件。我解决了问题。这是因为我没有返回promise.map()中生成的承诺。为您的帮助干杯。