2013-10-22 11 views
8

मैं सख्त उत्पादन के लिए कोशिश कर रहा हूँ एक पीडीएफ phantomJS द्वारा उत्पन्न stdout को herephantomjs पीडीएफ stdout को

की तरह क्या मैं हो रही है एक खाली पीडीएफ फाइल है, हालांकि यह आकार में नहीं 0 है, यह एक रिक्त पृष्ठ प्रदर्शित करता है।

var page = require('webpage').create(), 
system = require('system'), 
address; 

address = system.args[1]; 
page.paperSize = {format: 'A4'}; 

page.open(address, function (status) { 
    if (status !== 'success') { 
     console.log('Unable to load the address!'); 
     phantom.exit(); 
    } else { 
     window.setTimeout(function() { 
      page.render('/dev/stdout', { format: 'pdf' }); 
      phantom.exit(); 
     }, 1000); 
    } 
}); 

और मैं यह इतना की तरह फोन: phantomjs rasterize.js http://google.com>test.pdf

मैं बदल रहा /dev/stdout करने के लिए system.stdout नहीं बल्कि भाग्य की कोशिश की। किसी भी समस्या के बिना सीधे काम करने के लिए पीडीएफ लिखना।

मैं एक पार मंच कार्यान्वयन रहा हूँ, इसलिए मुझे आशा है कि इस गैर Linux सिस्टम पर प्राप्त है।

+0

फ़ैंटोमज का कौन सा संस्करण? नवीनतम संस्करण में उन्नयन करने का प्रयास करें। – philfreo

+1

मैं यह समस्या 1.9.2 Win8x64 पर देख रहा हूं। आउटपुट को पाइप करने से कंसोल में कुछ पीडीएफ सामग्री नहीं होती है, लेकिन आउटपुट को सीधे phantomjs rasterize.js> test.pdf के माध्यम से फ़ाइल करने के लिए कुछ भी नहीं चल रहा है। –

+0

@philfreo मैं Win7 – michaeltintiuc

उत्तर

15

निम्न चरणों के माध्यम से जब /dev/stdout/ या /dev/stderr/ विंडोज पर करने के लिए उत्पादन लेखन, PhantomJS चला जाता है (के रूप में देखा \phantomjs\src\webpage.cpp में render विधि):

  1. /dev/stdout/ और /dev/stderr/ एक tem के अभाव में पोरी फ़ाइल पथ आवंटित किया गया है।
  2. अस्थायी फ़ाइल पथ के साथ कॉल renderPdf
  3. इस फ़ाइल पथ पर वेब पेज प्रस्तुत करें।
  4. एक QByteArray में इस फ़ाइल की सामग्री पढ़ें।
  5. बाइट सरणी पर कॉल QString::fromAscii और stdout या stderr लिखें।
  6. अस्थायी फ़ाइल हटाएं।

आरंभ करने के लिए, मैंने PhantomJS के लिए स्रोत बनाया, लेकिन फ़ाइल हटाने को टिप्पणी की। अगले भाग पर, मैं प्रस्तुत की गई अस्थायी फ़ाइल की जांच करने में सक्षम था, जो पूरी तरह से ठीक हो गया। मैंने उसी परिणाम के साथ phantomjs.exe rasterize.js http://google.com > test.png चलाने का भी प्रयास किया। इसने तुरंत एक प्रतिपादन समस्या, या विशेष रूप से पीडीएफ के साथ कुछ भी करने का फैसला किया, जिसका अर्थ है कि समस्या को stdout पर डेटा के तरीके से संबंधित होना चाहिए।

इस स्तर तक मैं इस बारे में है कि क्या वहाँ कुछ पाठ एन्कोडिंग shenanigans पर जा रहा था संदेह था। पिछले रनों से, मेरे पास एक ही फ़ाइल का वैध और अमान्य संस्करण था (इस मामले में एक पीएनजी)।

//Read the contents of the known good file. 
byte[] bytesFromGoodFile = File.ReadAllBytes("valid_file.png"); 
//Read the contents of the known bad file. 
byte[] bytesFromBadFile = File.ReadAllBytes("invalid_file.png"); 

//Take the bytes from the valid file and convert to a string 
//using the Latin-1 encoding. 
string iso88591String = Encoding.GetEncoding("iso-8859-1").GetString(bytesFromGoodFile); 
//Take the Latin-1 encoded string and retrieve its bytes using the UTF-8 encoding. 
byte[] bytesFromIso88591String = Encoding.UTF8.GetBytes(iso88591String); 

//If the bytes from the Latin-1 string are all the same as the ones from the 
//known bad file, we have an encoding problem. 
Debug.Assert(bytesFromBadFile 
    .Select((b, i) => b == bytesFromIso88591String[i]) 
    .All(c => c)); 

ध्यान दें कि मैं QT के रूप में ISO-8859-1 एन्कोडिंग का प्रयोग किया default encoding for c-strings के रूप में इस का उपयोग करता है:

कुछ सी # कोड का उपयोग करना, मैं निम्नलिखित प्रयोग भाग गया। जैसे ही यह निकला, वे सभी बाइट एक जैसे थे। उस अभ्यास का मुद्दा यह देखना था कि क्या मैं एन्कोडिंग चरणों की नकल कर सकता हूं जिससे वैध डेटा अमान्य हो गया है।

आगे के सबूत के लिए, मैंने \phantomjs\src\system.cpp और \phantomjs\src\filesystem.cpp की जांच की।

  • system.cpp में, System वर्ग, अन्य बातों के अलावा, stdout, stdin और stderr के लिए File वस्तुओं, जो स्थापित कर रहे हैं UTF-8 एन्कोडिंग का उपयोग करना के लिए संदर्भ रखती है।
  • जब stdout के लिए लिख, File वस्तु की write समारोह कहा जाता है। यह समारोह दोनों पाठ और बाइनरी फ़ाइलें के लिए लिख का समर्थन करता है, लेकिन क्योंकि रास्ते से System वर्ग उन्हें initializes, सभी लेखन जैसे कि यह एक पाठ फ़ाइल में जा रहे थे माना जाएगा।

तो समस्या यह करने पर निर्भर करता: हम stdout किसी बाइनरी लिखने प्रदर्शन करने की जरूरत है, फिर भी हमारे लेखन अंत पाठ और एक एन्कोडिंग उन्हें करने के लिए लागू है कि परिणामी फ़ाइल का कारण बनता है को अमान्य घोषित किया होने के रूप में इलाज किया जा रहा।


को देखते हुए समस्या ऊपर वर्णित है, मैं PhantomJS कोड में बदलाव किए बिना इस तरह से आप विंडोज पर चाहते हैं काम कर पाने के लिए किसी भी तरह नहीं देख सकता। तो यहाँ वे हैं:

यह पहला परिवर्तन एक समारोह हम File वस्तुओं पर कॉल कर सकते हैं स्पष्ट रूप से एक द्विआधारी लिखने प्रदर्शन करने के लिए प्रदान करेगा। आसपास

bool File::binaryWrite(const QString &data) 
{ 
    if (!m_file->isWritable()) { 
     qDebug() << "File::write - " << "Couldn't write:" << m_file->fileName(); 
     return true; 
    } 

    QByteArray bytes(data.size(), Qt::Uninitialized); 
    for(int i = 0; i < data.size(); ++i) { 
     bytes[i] = data.at(i).toAscii(); 
    } 
    return m_file->write(bytes); 
} 

:

\phantomjs\src\filesystem.h में निम्नलिखित समारोह प्रोटोटाइप जोड़ें:

bool binaryWrite(const QString &data); 

और (कोड के लिए इस विधि इस फ़ाइल में write विधि से आता है) \phantomjs\src\filesystem.cpp में इसकी परिभाषा जगह लाइन 920 \phantomjs\src\webpage.cpp की आप कोड का एक खंड देखेंगे कि इस तरह दिखता है:

if(fileName == STDOUT_FILENAME){ 
#ifdef Q_OS_WIN32 
     _setmode(_fileno(stdout), O_BINARY);    
#endif  

     ((File *)system->_stderr())->write(QString::fromAscii(name.constData(), name.size())); 

#ifdef Q_OS_WIN32 
     _setmode(_fileno(stdout), O_TEXT); 
#endif   
    } 

इस के बदले यह:

if(fileName == STDOUT_FILENAME){ 
#ifdef Q_OS_WIN32 
     _setmode(_fileno(stdout), O_BINARY); 
     ((File *)system->_stdout())->binaryWrite(QString::fromAscii(ba.constData(), ba.size())); 
#elif    
     ((File *)system->_stderr())->write(QString::fromAscii(name.constData(), name.size())); 
#endif  

#ifdef Q_OS_WIN32 
     _setmode(_fileno(stdout), O_TEXT); 
#endif   
    } 

तो क्या है कि कोड प्रतिस्थापन करता है हमारे नए binaryWrite समारोह कहता है, लेकिन इतना एक #ifdef Q_OS_WIN32 ब्लॉक द्वारा सुरक्षित है। मैंने ऐसा इसलिए किया ताकि गैर-विंडोज सिस्टम पर पुरानी कार्यक्षमता को संरक्षित किया जा सके जो इस समस्या को प्रदर्शित नहीं कर रहे हैं (या वे करते हैं?)। ध्यान दें कि यह ठीक ही stdout के लिए लिख करने के लिए लागू होता है - अगर आप चाहते हैं करने के लिए आप हमेशा stderr करने के लिए इसे लागू हो सकते हैं, लेकिन यह काफी ताकि मामले में ज्यादा फर्क नहीं कर सकते हैं।

यदि आप केवल पूर्व निर्मित बाइनरी (कौन नहीं करेंगे) चाहते हैं, तो आप phantomjs.exe को अपने SkyDrive पर इन फ़िक्सेस के साथ पा सकते हैं। मेरा संस्करण लगभग 1 9 एमबी है जबकि मैंने पहले डाउनलोड किया था केवल 6 एमबी था, हालांकि मैंने here निर्देशों का पालन किया, इसलिए यह ठीक होना चाहिए।

+0

यह आश्चर्यजनक है, आपकी मदद के लिए बहुत बहुत धन्यवाद, समय और प्रयास इस जवाब में डाल दिया! – michaeltintiuc

0

यह उत्पादन के लिए अनिवार्य पीडीएफ stdout करने के लिए है? आप के लिए कोड नहीं बदल सका:

var page = require('webpage').create(), 
system = require('system'), 
address; 

address = system.args[1]; 
output = system.args[2]; 
page.paperSize = {format: 'A4'}; 

page.open(address, function (status) { 
    if (status !== 'success') { 
     console.log('Unable to load the address!'); 
     phantom.exit(); 
    } else { 
     window.setTimeout(function() { 
      page.render(output, { format: 'pdf' }); 
      phantom.exit(); 
     }, 1000); 
    } 
}); 

और इस तरह इसका इस्तेमाल:

phantomjs rasterize.js http://google.com test.pdf 
+0

यही वह काम है जो मैं आसपास के काम के रूप में कर रहा था, लेकिन मेरा विचार फ्लाई पर पीडीएफ बनाना था। नोड-वेबकिट पुश और फैंटोमज के बीच डेटा को दबाकर आगे बढ़ाएं। – michaeltintiuc

+0

मैं एक गहरी लुक दूंगा, शायद कुछ ऐसा चरित्र है जो पीडीएफ संरचना को गड़बड़ कर रहा है। –

7

हां, यह सही है आईएसओ -885 9 -1 क्यूटी के लिए डिफ़ॉल्ट एन्कोडिंग है, इसलिए आपको कमांड लाइन - आउटपुट-एन्कोडिंग = आईएसओ -885 9 -1 में आवश्यक पैरामीटर जोड़ना होगा ताकि पीडीएफ आउटपुट नहीं होगा

दूषित हो यानी

phantomjs.exe rasterize.js --output एन्कोडिंग = ISO-8859-1 < input.html> output.pdf

और rasterize.js (परीक्षण दोनों यूनिक्स और विंडोज के लिए काम करता है) इस तरह दिखता है

var page = require('webpage').create(), 
system = require('system'); 

page.viewportSize = {width: 600, height: 600}; 
page.paperSize = {format: 'A4', orientation: system.args[1], margin: '1cm'}; 

page.content = system.stdin.read(); 

window.setTimeout(function() { 
    try { 
     page.render('/dev/stdout', {format: 'pdf'}); 
    } 
    catch (e) { 
     console.log(e.message + ';;' + output_file); 
    } 
    phantom.exit(); 
}, 1000); 

या वैकल्पिक रूप से आप stdout का उपयोग कर एन्कोडिंग सेट कर सकते हैं और यदि आप UTF-8 धारा से पढ़ रहे हैं तो आप के रूप में अच्छी stdin के लिए एन्कोडिंग सेट करने के लिए हो सकता है;

system.stdout.setEncoding('ISO-8859-1'); 
system.stdin.setEncoding('UTF-8'); 
page.content = system.stdin.read(); 
+1

धन्यवाद आदमी, पागल कैसे इस तरह के एक पुराने सवाल को एक नया जवाब मिला, आपके समय के लिए धन्यवाद! मैं थोड़ी देर के लिए उस परियोजना पर काम नहीं कर रहा था, लेकिन जल्द ही इसे फिर से देखूंगा। – michaeltintiuc

+1

'system.stdout.setEncoding ('ISO-8859-1');' <- इस लाइन मुझे डीबगिंग के घंटे के बाद बचा लिया। इस उत्तर के लिए बहुत बहुत धन्यवाद !! – Khan

+0

@Khan कोई चिंता नहीं :) – Pinchy