निम्न चरणों के माध्यम से जब /dev/stdout/
या /dev/stderr/
विंडोज पर करने के लिए उत्पादन लेखन, PhantomJS
चला जाता है (के रूप में देखा \phantomjs\src\webpage.cpp में render
विधि):
/dev/stdout/
और /dev/stderr/
एक tem के अभाव में पोरी फ़ाइल पथ आवंटित किया गया है।
- अस्थायी फ़ाइल पथ के साथ कॉल
renderPdf
।
- इस फ़ाइल पथ पर वेब पेज प्रस्तुत करें।
- एक
QByteArray
में इस फ़ाइल की सामग्री पढ़ें।
- बाइट सरणी पर कॉल
QString::fromAscii
और stdout
या stderr
लिखें।
- अस्थायी फ़ाइल हटाएं।
आरंभ करने के लिए, मैंने 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 निर्देशों का पालन किया, इसलिए यह ठीक होना चाहिए।
फ़ैंटोमज का कौन सा संस्करण? नवीनतम संस्करण में उन्नयन करने का प्रयास करें। – philfreo
मैं यह समस्या 1.9.2 Win8x64 पर देख रहा हूं। आउटपुट को पाइप करने से कंसोल में कुछ पीडीएफ सामग्री नहीं होती है, लेकिन आउटपुट को सीधे phantomjs rasterize.js> test.pdf के माध्यम से फ़ाइल करने के लिए कुछ भी नहीं चल रहा है। –
@philfreo मैं Win7 – michaeltintiuc