2012-10-26 14 views
8

मैं wkhtmltopdf.exe का उपयोग करके पीडीएफ के रूप में एक HTML दस्तावेज़ प्रस्तुत करने का प्रयास कर रहा हूं, जिसे मैं एक सी # वेब एप्लिकेशन से कॉल करता हूं।WkHtmlToPDF - stdin और headers/footers के साथ काम करना

एचटीएमएल दस्तावेज़ में प्रत्येक पृष्ठ पर दोहराए जाने वाले एक पाद लेख और शीर्षलेख की आवश्यकता होती है, जो --header-html <a path> को तर्क के रूप में निर्दिष्ट करके wkhtmltopdf के साथ संभव है।

हालांकि, पाद लेख को रेज़र दृश्य से गतिशील रूप से प्रस्तुत किया जाता है और मुझे इसे डिस्क पर एक अस्थायी फ़ाइल में संग्रहीत करने की आवश्यकता नहीं होगी और उस पथ का उपयोग करने की आवश्यकता नहीं है, लेकिन मैं प्रस्तुत किए गए HTML का उपयोग करना चाहता हूं जो पहले से ही स्मृति में है। यही कारण है कि संभव है स्वयं दस्तावेज़ के लिए, StandardInput धारा के लिए लिख, इसलिए तरह से:

var wkhtml = ConfigurationManager.AppSettings["WkHtmlToPdfPath"]; 
var p = new Process(); 

p.StartInfo.CreateNoWindow = true; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.RedirectStandardError = true; 
p.StartInfo.RedirectStandardInput = true; 
p.StartInfo.UseShellExecute = false; 
p.StartInfo.FileName = wkhtml; 

p.StartInfo.Arguments = "-q -n --disable-smart-shrinking - -"; 
p.Start(); 

var stdin = p.StandardInput; 
stdin.AutoFlush = true; 
stdin.Write(template); 
stdin.Dispose(); 

शीर्ष लेख और पाद HTML के लिए एक ही बात करने के लिए क्या यह संभव है, अर्थात् का सहारा के बिना इनलाइन में इसे पारित करने के अस्थायी फ़ाइलें?

मैं कोशिश की है:

stdin.Write(string.Format("--footer-html {0} ", footer)); 

लेकिन निश्चित रूप से, यह सिर्फ व्यवहार करता है कि दस्तावेज़, नहीं एक पाद लेख के भाग के रूप।

मुख्य कारण मैं पाद लेख और शीर्षलेख को गतिशील रूप से प्रस्तुत करना चाहता हूं (ज्यादातर) किसी अन्य मुद्दे के कारण होता है। हालांकि गतिशील शीर्षलेख और पाद लेख होना अच्छा लगेगा, यह ज्यादातर समस्या को हल करने के लिए है जो मुझे पूर्ण पथ (यानी: सी: \ टेम्पलेट्स \ images \ logo.png) वाली छवियों से लिंक करना है क्योंकि सापेक्ष पथ (यानी: छवियों/logo.png) जब आप stdin का उपयोग करते हैं तो काम नहीं करते हैं और बस HTML के स्ट्रिंग ब्लॉब में पास होते हैं, इसलिए मुझे रनटाइम पर रेजर के माध्यम से पूर्ण पथ डालना होगा।

इस मुद्दे के लिए, मैं प्रक्रिया संबंधित पथ से मेल करने की कार्यशील निर्देशिका स्थापित करने की कोशिश की है, लेकिन कोई लाभ नहीं हुआ:

p.StartInfo.WorkingDirectory = @"C:\templates"; 

मुझे लगता है कि समस्या का समाधान कर सकता है, कि के 90% हल होगा मुद्दा भी।

+2

मेरे पास एक ही समस्या है, लेकिन चूंकि Wkhtmltopdf हेडर/पादर्स को अलग करता है (बाहरी पथ/यूआरएल के माध्यम से) मैं एक HTML दस्तावेज़ को परिभाषित करता हूं जिसे मैंने गतिशील डेटा को अपने यूआरएल में खिलाया।तब मैंने कुछ जावास्क्रिप्ट के साथ निकाला। – Alex

उत्तर

3

ध्यान दें कि आपने इस जूलियनआर को हल किया है, और मैं यह भी मानूंगा कि आप एमवीसी (?) में हैं, यदि आप नीचे दिए गए कुछ शुरुआती कोड को अनदेखा नहीं कर सकते हैं, लेकिन मेरे पास एक समान स्थिति थी जिससे मुझे सीधे आउटपुट स्ट्रीम करने की आवश्यकता थी किसी साइट के अनुभागों में सुरक्षित और लॉग इन होने के कारण wkhtmltopdf पर।

सबसे पहले एक नियंत्रक में आप देखें कि आप किसी भी लागू मास्टर पृष्ठ के साथ प्रदर्शित करने के लिए की जरूरत है (जो अपने आप शीर्षलेख और पादलेख उपयोग कर सकते हैं) में खींच सकते हैं:

var view = ViewEngines.Engines.FindView(ControllerContext, myViewName, myMasterPageLayout); 

आप तो साथ इस देखने के एक वर्तमान मिल किसी भी आवश्यक ViewData, Tempdata, आदि और एक स्ट्रिंग में संग्रहीत कर (नीचे सामग्री):

string content; 
ViewData.Model = model; 
using (var writer = new System.IO.StringWriter()) 
{ 
    var context = new ViewContext(ControllerContext, view.View, ViewData, TempData, writer); 
    view.View.Render(context, writer); 
    writer.Flush(); 
    content = writer.ToString(); 
    writer.Close(); 
} 

इस स्तर पर आप वास्तव में स्ट्रिंग में अपने उत्पादन एचटीएमएल को संशोधित कर सकता है अगर जरूरत है - जैसे पूर्ण पथ

आप के साथ

आउटपुट HTML आप तो बस wkhtmltopdf में पारित करने के लिए किसी भी स्थानीय पथ को बदलने के लिए:

var p = new Process(); 
p.StartInfo.CreateNoWindow = true; 
p.StartInfo.RedirectStandardOutput = true; 
p.StartInfo.RedirectStandardError = true; 
p.StartInfo.RedirectStandardInput = true; 
p.StartInfo.UseShellExecute = false; 
//Other parameters as required 
byte[] file; 
try 
{ 
    p.Start(); 
    byte[] buffer = new byte[32768]; 

    using (System.IO.StreamWriter stdin = p.StandardInput) 
    { 
     stdin.AutoFlush = true; 
     stdin.Write(content); 
    } 


    using (MemoryStream ms = new MemoryStream()) 
    { 
     ms.Position = 0; 
     p.StandardOutput.BaseStream.CopyTo(ms); 
     file = ms.ToArray(); 
    } 

    p.StandardOutput.Close(); 
    // wait or exit 
    p.WaitForExit(60000); 

    // read the exit code, close process 
    int returnCode = p.ExitCode; 

} 

आप तो एक बाइट सरणी है कि पूरे पेज के अपने पीडीएफ सामग्री शामिल है।

+0

जानकारी के लिए धन्यवाद। मैंने इस समस्या को हल करने का अंत नहीं किया और इसके बजाय माइक्रोसॉफ्ट आरडीएलसी रिपोर्टों का इस्तेमाल किया, जिसमें रिपोर्ट संपादित करते समय काफी कठोरता के बावजूद कई फायदे (सादगी, मूल मुद्रण समर्थन) थे। – JulianR

संबंधित मुद्दे