Node.js - tar 文件的 exec 命令第一次运行正常,但在后续执行时产生损坏的 tar 内容
Node.js - exec command for tar files works correctly first time, but produces corrupted tar contents upon subsequent execution
我正在使用 Node.js 构建一个网络应用程序,我正处于需要生成 PDF 目录的 tar 存档的时刻。该应用程序 运行 在 VM 运行 Ubuntu 14.04 服务器上。我的代码如下所示:
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();
});
}
而这个tar目录函数由以下代码调用:
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 请求,其中包含通过在我的网络应用程序中单击按钮生成的动态数据,然后将根据数据创建文件并将其 tar 放入目录中。这一切都很好……第一次。当我第一次点击按钮时,会生成 tar ,当我打开它时,客户端的 PDF 与服务器上的相同。但是,当我在大约一个小时内再次单击时,我收到了一个 tar 文件,但是当我打开存档并将其解压缩时,PDF 全部损坏并且大约是预期字节大小的一半。我在这里不知所措......我怀疑这可能与流关闭处理不当有关,但我不确定。
这是将 PDF 生成到目录中的代码,生成后 tar 红色:
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();
}
- 压缩前 pdf 文件是否一切正常?
- 在您的
generateFile
函数中,您有 WriteStream,它是异步的。但是,您将此函数称为 sync.,并且 start .tar 压缩而没有等待 pdf 生成完成,这可能会导致此问题。
- 作为建议:尝试用 promise 包装
generateFile
,或者迭代异步,并且仅在所有文件生成完成后才进行 tart 压缩。
蓝鸟示例:
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();
});
}
Pdfs 生成和压缩。
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();
});
});
}
以及调用两个辅助函数的代码:
// 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);
});
});
非常感谢任何关于我在这里可能做错了什么的进一步见解。
我正在使用 Node.js 构建一个网络应用程序,我正处于需要生成 PDF 目录的 tar 存档的时刻。该应用程序 运行 在 VM 运行 Ubuntu 14.04 服务器上。我的代码如下所示:
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();
});
}
而这个tar目录函数由以下代码调用:
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 请求,其中包含通过在我的网络应用程序中单击按钮生成的动态数据,然后将根据数据创建文件并将其 tar 放入目录中。这一切都很好……第一次。当我第一次点击按钮时,会生成 tar ,当我打开它时,客户端的 PDF 与服务器上的相同。但是,当我在大约一个小时内再次单击时,我收到了一个 tar 文件,但是当我打开存档并将其解压缩时,PDF 全部损坏并且大约是预期字节大小的一半。我在这里不知所措......我怀疑这可能与流关闭处理不当有关,但我不确定。
这是将 PDF 生成到目录中的代码,生成后 tar 红色:
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();
}
- 压缩前 pdf 文件是否一切正常?
- 在您的
generateFile
函数中,您有 WriteStream,它是异步的。但是,您将此函数称为 sync.,并且 start .tar 压缩而没有等待 pdf 生成完成,这可能会导致此问题。 - 作为建议:尝试用 promise 包装
generateFile
,或者迭代异步,并且仅在所有文件生成完成后才进行 tart 压缩。
蓝鸟示例:
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();
});
}
Pdfs 生成和压缩。
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();
});
});
}
以及调用两个辅助函数的代码:
// 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);
});
});
非常感谢任何关于我在这里可能做错了什么的进一步见解。