2016-08-08 26 views
1

我正在用Node.js構建一個Web應用程序,而且我正需要生成一個tar歸檔文件的PDF目錄。該應用程序在運行Ubuntu 14.04服務器的虛擬機上運行。我的代碼來執行此如下所示:Node.js - 用於tar文件的exec命令第一次正常工作,但在後續執行時會產生損壞的tar內容

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請求,其由按鈕點擊所產生在我的網絡應用程序中,然後將根據數據創建文件並將其打包到目錄中。這一切都很好,第一次。當我第一次點擊按鈕時,會產生焦油,當我打開它時,客戶端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(); 
} 

回答

0
  1. 一切都好PDF文件,壓縮前?
  2. 在你的generateFile函數中,你有WriteStream,它是異步的。但是,您將此函數稱爲同步,並且在pdf生成完成之前無需等待就可以啓動.tar壓縮,這可能會導致此問題。
  3. 作爲建議:嘗試用promise包裝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 
    }); 
+0

1.是的,PDFs在服務器上的原始文件夾中是完整的,所以它們肯定是正確生成的。 2.我認爲這是正確的軌道...我會考慮使用承諾這一點。 3。謝謝你的例子:) – Kw3si

+0

因此,在實現你對promise的建議之後,如果它一次只生成一個,我就能夠正確地生成PDF。調查......將返回給您 – Kw3si

0

所以我實現了Nazar建議的承諾。如果我只生成一個文件,現在總的操作基本沒問題,但如果我生成的文件更多,我會得到相同的損壞的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(); 
    }); 
} 

我的代碼焦油目錄:

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); 
    }); 
}); 

對於我在這裏可能做錯什麼的任何進一步見解都非常感謝。

+0

做下一步:'function generateFile',用'resolve({id:id,path:filePath})'替換'resolve()''。 和'Promise.map' - 首先'.then(函數()'與'然後(函數(文件)'。 打印這些文件,以驗證名稱是否正確。沒有足夠的信息。你試圖寫入同一個文件 –

+0

我解決了這個問題,這是因爲我沒有返回Promise.map()中生成的諾言,歡呼你所有的幫助Nazar。 – Kw3si

相關問題