2012-06-20 98 views
2

我使用child_process運行wkhtmltopdf以從html文檔構建PDF。在繼續之前,我想等到wkhtmltopdf完成將文檔處理爲PDF格式。我認爲當wkhtmltopdf發送完成信號時,從stdout中讀取以捕獲是最好的方法,但是下面的代碼報告stdout在res.send()處爲空。當stdout向我提供數據時,如何設置要觸發的事件?Node.js - 等到文件完全寫入

代碼:

var buildPdf = function(error){ 
    var pdfLetter; 

    var child = exec('wkhtmltopdf temp.html compensation.pdf', function(error, stdout, stderr) { 
     if (error) 
      res.send({ 
       err:error.message 
       }); 
     else 
      res.send({ 
       output : stdout.toString() 
     }); 
        // sendEmail(); 
    }); 
}; 

回答

4

你已經遇到了wkhtmltopdf疑難雜症。它不會將狀態信息寫入STDOUT,它將其寫入STDERR。

$ node -e \ 
    "require('child_process').exec(\ 
    'wkhtmltopdf http://stackoverflow.com/ foo.pdf', \ 
    function(err, stdout, stderr) { process.stdout.write(stderr); });" 
Loading pages (1/6) 
content-type missing in HTTP POST, defaulting to application/octet-stream 
Counting pages (2/6) 
Resolving links (4/6) 
Loading headers and footers (5/6) 
Printing pages (6/6) 
Done 
+0

你能解釋所有爲什麼是這樣的情況? – Menztrual

+0

@tehlulz大概是這樣,你可以看到它的進度,同時也將其輸出管道輸出到另一個進程/文件描述符(例如'wkhtmltopdf foo.html - | gzip> foo.gz')。 –

+0

這是什麼巫術! :P – Menztrual

0

我剛剛完成得到這個通過Node.js的工作在Heroku和想後,因爲我必須克服幾個小小的障礙。

// Spin up a new child_process to handle wkhtmltopdf. 
var spawn = require('child_process').spawn; 

// stdin/stdout, but see below for writing to tmp storage. 
wkhtmltopdf = spawn('./path/to/wkhtmltopdf', ['-', '-']); 

// Capture stdout (the generated PDF contents) and append it to the response. 
wkhtmltopdf.stdout.on('data', function (data) { 
    res.write(data); 
}); 

// On process exit, determine proper response depending on the code. 
wkhtmltopdf.on('close', function (code) { 
    if (code === 0) { 
     res.end(); 
    } else { 
     res.status(500).send('Super helpful explanation.'); 
    } 
}); 

res.header('Content-Type', 'application/octet-stream'); 
res.header('Content-Disposition', 'attachment; filename=some_file.pdf'); 
res.header('Expires', '0'); 
res.header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0'); 

// Write some markup to wkhtmltopdf and then end the process. The .on 
// event above will be triggered and the response will get sent to the user. 
wkhtmltopdf.stdin.write(some_markup); 
wkhtmltopdf.stdin.end(); 

論的Heroku雪松-14疊,我不能讓wkhtmltopdf寫入標準輸出。服務器始終以Unable to write to destination迴應。訣竅有寫信給./.tmp,然後流書面文件回給用戶 - 很容易的:

wkhtmltopdf = spawn('./path/to/wkhtmltopdf', ['-', './.tmp/some_file.pdf']); 

wkhtmltopdf.on('close', function (code) { 
    if (code === 0) { 

     // Stream the file. 
     fs.readFile('./.tmp/some_file.pdf', function(err, data) { 

      res.header('Content-Type', 'application/octet-stream'); 
      res.header('Content-Disposition', 'attachment; filename=' + filename); 
      res.header('Expires', '0'); 
      res.header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0'); 

      res.send(data); 
     }); 
    } else { 
     res.status(500).send('Super helpful explanation.'); 
    } 
}); 

res.header('Content-Type', 'application/octet-stream'); 
res.header('Content-Disposition', 'attachment; filename=' + filename); 
res.header('Expires', '0'); 
res.header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');