Example #1
0
        public static PdfFileGeneratedIntegrationEvent ConsumeAsync(PdfDocumentGenerateIntegrationEvent document)
        {
            Console.WriteLine("Pdf File Generate Integration Event Received: {0}", document.DisputeGuid);

            PdfOutput pdfOutput = new PdfOutput()
            {
                OutputStream = new MemoryStream()
            };

            PdfConvert.ConvertHtmlToPdf(document, pdfOutput);

            var bytes = ((MemoryStream)pdfOutput.OutputStream).ToArray();

            if (bytes != null)
            {
                pdfOutput.OutputStream.Close();

                var base64File = Convert.ToBase64String(bytes);

                var pdfFile = new PdfFileGeneratedIntegrationEvent
                {
                    CreatedDateTime   = document.CreatedDateTime,
                    DisputeGuid       = document.DisputeGuid,
                    FileContentBase64 = base64File
                };

                return(pdfFile);
            }

            return(null);
        }
Example #2
0
 public Stream GeneratePdfStream(string url)
 {
     var document = new PdfDocument { Url = url };
     var output = new PdfOutput {OutputStream = new MemoryStream()};
     PdfConvert.ConvertHtmlToPdf(document, output);
     output.OutputStream.Position = 0;
     return output.OutputStream;
 }
Example #3
0
        public Stream ExportToCSV(PdfOutput input)
        {
            var stream = new MemoryStream();

            using (var writeFile = new StreamWriter(stream, leaveOpen: true))
            {
                var configuration = new CsvConfiguration(new CultureInfo("de-DE"));
                input.Data.ForEach(d => d.ForigenAmount = d.ForigenAmount.Replace(".", ","));
                var csv = new CsvWriter(writeFile, configuration, true);
                csv.WriteRecords(input.Data);
                writeFile.Flush();
            }
            stream.Position = 0; //reset stream

            return(stream);
        }
Example #4
0
        public MemoryStream PdfStream(string url)
        {
            var memory   = new MemoryStream();
            var document = new PdfDocument()
            {
                Url = url
            };
            var output = new PdfOutput()
            {
                OutputStream = memory
            };

            PdfConvert.ConvertHtmlToPdf(document, output);
            memory.Position = 0;

            return(memory);
        }
Example #5
0
        public ActionResult <string> Post([FromBody] PdfDocument document)
        {
            PdfOutput pdfOutput = new PdfOutput()
            {
                OutputStream = new MemoryStream()
            };

            PdfConvert.ConvertHtmlToPdf(document.Convert(), pdfOutput);

            var bytes = ((MemoryStream)pdfOutput.OutputStream).ToArray();

            if (bytes != null)
            {
                pdfOutput.OutputStream.Close();

                return(Ok(Convert.ToBase64String(bytes)));
            }

            return(StatusCode(404));
        }
Example #6
0
        public void Transform(IEnumerable <Element> elements, Stream output)
        {
            Compositor compositor = new Compositor();
            var        root       = compositor.RootPageCollection
                                    .MediaBox(0, 0, (int)PageSettings.InPoints(_settings.PageWidth), (int)PageSettings.InPoints(_settings.PageHeight))
                                    .AddResources()
                                    .AddSimpeType1Font("Courier", out _courier)
                                    .AddSimpeType1Font("Courier-Bold", out _courierBold)
                                    .AddSimpeType1Font("Courier-Oblique", out _courierItalic)
                                    .AddSimpeType1Font("Courier-BoldOblique", out _courierBoldItalic)
                                    .End();

            _page = NewPage(root);

            WriteTitleElement(elements.FirstOrDefault() as TitleElement);

            foreach (var element in elements)
            {
                bool found = Write(element as DialogGroupElement) ||
                             Write(element as ActionElement) ||
                             Write(element as HeadingElement) ||
                             Write(element as TransitionElement) ||
                             Write(element as CenteredTextElement) ||
                             Write(element as BoneyardElement) ||
                             Write(element as NoteBlockElement) ||
                             Write(element as SectionElement);

                if (!found)
                {
                    Console.WriteLine("NOT FOUND: {0}", element.Type);
                }
            }

            TextWriter w         = new StreamWriter(output);
            PdfOutput  pdfOutput = new PdfOutput(w);

            pdfOutput.WriteCompositor(compositor);
            w.Flush();
        }
Example #7
0
            public static void ConvertHtmlToPdf(PdfDocument document, PdfConvertEnvironment environment, PdfOutput woutput)
            {
                if (environment == null)
                {
                    environment = Environment;
                }

                if (document.Html != null)
                {
                    document.Url = "-";
                }

                String outputPdfFilePath;
                bool   delete;

                if (woutput.OutputFilePath != null)
                {
                    outputPdfFilePath = woutput.OutputFilePath;
                    delete            = false;
                }
                else
                {
                    outputPdfFilePath = Path.Combine(environment.TempFolderPath, String.Format("{0}.pdf", Guid.NewGuid()));
                    delete            = true;
                }

                if (!File.Exists(environment.WkHtmlToPdfPath))
                {
                    throw new PdfConvertException(String.Format("File '{0}' not found. Check if wkhtmltopdf application is installed.", environment.WkHtmlToPdfPath));
                }

                StringBuilder paramsBuilder = new StringBuilder();

                paramsBuilder.Append("--page-size A4 ");

                if (!string.IsNullOrEmpty(document.HeaderUrl))
                {
                    paramsBuilder.AppendFormat("--header-html {0} ", document.HeaderUrl);
                    paramsBuilder.Append("--margin-top 25 ");
                    paramsBuilder.Append("--header-spacing 5 ");
                }
                if (!string.IsNullOrEmpty(document.FooterUrl))
                {
                    paramsBuilder.AppendFormat("--footer-html {0} ", document.FooterUrl);
                    paramsBuilder.Append("--margin-bottom 25 ");
                    paramsBuilder.Append("--footer-spacing 5 ");
                }
                if (!string.IsNullOrEmpty(document.HeaderLeft))
                {
                    paramsBuilder.AppendFormat("--header-left \"{0}\" ", document.HeaderLeft);
                }

                if (!string.IsNullOrEmpty(document.HeaderCenter))
                {
                    paramsBuilder.AppendFormat("--header-center \"{0}\" ", document.HeaderCenter);
                }

                if (!string.IsNullOrEmpty(document.HeaderRight))
                {
                    paramsBuilder.AppendFormat("--header-right \"{0}\" ", document.HeaderRight);
                }

                if (!string.IsNullOrEmpty(document.FooterLeft))
                {
                    paramsBuilder.AppendFormat("--footer-left \"{0}\" ", document.FooterLeft);
                }

                if (!string.IsNullOrEmpty(document.FooterCenter))
                {
                    paramsBuilder.AppendFormat("--footer-center \"{0}\" ", document.FooterCenter);
                }

                if (!string.IsNullOrEmpty(document.FooterRight))
                {
                    paramsBuilder.AppendFormat("--footer-right \"{0}\" ", document.FooterRight);
                }

                if (!string.IsNullOrEmpty(document.HeaderFontSize))
                {
                    paramsBuilder.AppendFormat("--header-font-size \"{0}\" ", document.HeaderFontSize);
                }

                if (!string.IsNullOrEmpty(document.FooterFontSize))
                {
                    paramsBuilder.AppendFormat("--footer-font-size \"{0}\" ", document.FooterFontSize);
                }

                if (!string.IsNullOrEmpty(document.HeaderFontName))
                {
                    paramsBuilder.AppendFormat("--header-font-name \"{0}\" ", document.HeaderFontName);
                }

                if (!string.IsNullOrEmpty(document.FooterFontName))
                {
                    paramsBuilder.AppendFormat("--footer-font-name \"{0}\" ", document.FooterFontName);
                }


                if (document.ExtraParams != null)
                {
                    foreach (var extraParam in document.ExtraParams)
                    {
                        paramsBuilder.AppendFormat("--{0} {1} ", extraParam.Key, extraParam.Value);
                    }
                }

                if (document.Cookies != null)
                {
                    foreach (var cookie in document.Cookies)
                    {
                        paramsBuilder.AppendFormat("--cookie {0} {1} ", cookie.Key, cookie.Value);
                    }
                }

                paramsBuilder.AppendFormat("\"{0}\" \"{1}\"", document.Url, outputPdfFilePath);

                try
                {
                    StringBuilder output = new StringBuilder();
                    StringBuilder error  = new StringBuilder();

                    using (Process process = new Process())
                    {
                        process.StartInfo.FileName               = environment.WkHtmlToPdfPath;
                        process.StartInfo.Arguments              = paramsBuilder.ToString();
                        process.StartInfo.UseShellExecute        = false;
                        process.StartInfo.RedirectStandardOutput = true;
                        process.StartInfo.RedirectStandardError  = true;
                        process.StartInfo.RedirectStandardInput  = true;

                        using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
                            using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
                            {
                                DataReceivedEventHandler outputHandler = (sender, e) =>
                                {
                                    if (e.Data == null)
                                    {
                                        outputWaitHandle.Set();
                                    }
                                    else
                                    {
                                        output.AppendLine(e.Data);
                                    }
                                };

                                DataReceivedEventHandler errorHandler = (sender, e) =>
                                {
                                    if (e.Data == null)
                                    {
                                        errorWaitHandle.Set();
                                    }
                                    else
                                    {
                                        error.AppendLine(e.Data);
                                    }
                                };

                                process.OutputDataReceived += outputHandler;
                                process.ErrorDataReceived  += errorHandler;

                                try
                                {
                                    process.Start();

                                    process.BeginOutputReadLine();
                                    process.BeginErrorReadLine();

                                    if (document.Html != null)
                                    {
                                        using (var stream = process.StandardInput)
                                        {
                                            byte[] buffer = Encoding.UTF8.GetBytes(document.Html);
                                            stream.BaseStream.Write(buffer, 0, buffer.Length);
                                            stream.WriteLine();
                                        }
                                    }

                                    if (process.WaitForExit(environment.Timeout) && outputWaitHandle.WaitOne(environment.Timeout) && errorWaitHandle.WaitOne(environment.Timeout))
                                    {
                                        if (process.ExitCode != 0 && !File.Exists(outputPdfFilePath))
                                        {
                                            throw new PdfConvertException(String.Format("Html to PDF conversion of '{0}' failed. Wkhtmltopdf output: \r\n{1}", document.Url, error));
                                        }
                                    }
                                    else
                                    {
                                        if (!process.HasExited)
                                        {
                                            process.Kill();
                                        }

                                        throw new PdfConvertTimeoutException();
                                    }
                                }
                                finally
                                {
                                    process.OutputDataReceived -= outputHandler;
                                    process.ErrorDataReceived  -= errorHandler;
                                }
                            }
                    }


                    if (woutput.OutputStream != null)
                    {
                        using (Stream fs = new FileStream(outputPdfFilePath, FileMode.Open))
                        {
                            byte[] buffer = new byte[32 * 1024];
                            int    read;

                            while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                woutput.OutputStream.Write(buffer, 0, read);
                            }
                        }
                    }

                    if (woutput.OutputCallback != null)
                    {
                        byte[] pdfFileBytes = File.ReadAllBytes(outputPdfFilePath);
                        woutput.OutputCallback(document, pdfFileBytes);
                    }
                }
                finally
                {
                    if (delete && File.Exists(outputPdfFilePath))
                    {
                        File.Delete(outputPdfFilePath);
                    }
                }
            }
Example #8
0
 public static void ConvertHtmlToPdf(PdfDocument document, PdfOutput output)
 {
     ConvertHtmlToPdf(document, null, output);
 }
Example #9
0
        private async void cmdSaveAsPdf_Click(object sender, EventArgs e)
        {
            using (new CursorWait(this))
            {
                // Check to see if we have any "Print to PDF" printers, as they will be a lot more reliable than wkhtmltopdf
                string strPdfPrinter = string.Empty;
                foreach (string strPrinter in PrinterSettings.InstalledPrinters)
                {
                    if (strPrinter == "Microsoft Print to PDF" || strPrinter == "Foxit Reader PDF Printer" ||
                        strPrinter == "Adobe PDF")
                    {
                        strPdfPrinter = strPrinter;
                        break;
                    }
                }

                if (!string.IsNullOrEmpty(strPdfPrinter))
                {
                    DialogResult ePdfPrinterDialogResult = Program.MainForm.ShowMessageBox(this,
                                                                                           string.Format(GlobalSettings.CultureInfo,
                                                                                                         await LanguageManager.GetStringAsync("Message_Viewer_FoundPDFPrinter"), strPdfPrinter),
                                                                                           await LanguageManager.GetStringAsync("MessageTitle_Viewer_FoundPDFPrinter"),
                                                                                           MessageBoxButtons.YesNoCancel, MessageBoxIcon.Information);
                    switch (ePdfPrinterDialogResult)
                    {
                    case DialogResult.Cancel:
                    case DialogResult.Yes when DoPdfPrinterShortcut(strPdfPrinter):
                        return;

                    case DialogResult.Yes:
                        Program.MainForm.ShowMessageBox(this,
                                                        await LanguageManager.GetStringAsync("Message_Viewer_PDFPrinterError"));
                        break;
                    }
                }

                // Save the generated output as PDF.
                SaveFileDialog1.Filter = await LanguageManager.GetStringAsync("DialogFilter_Pdf") + '|' +
                                         await LanguageManager.GetStringAsync("DialogFilter_All");

                SaveFileDialog1.Title = await LanguageManager.GetStringAsync("Button_Viewer_SaveAsPdf");

                SaveFileDialog1.ShowDialog();
                string strSaveFile = SaveFileDialog1.FileName;

                if (string.IsNullOrEmpty(strSaveFile))
                {
                    return;
                }

                if (!strSaveFile.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase))
                {
                    strSaveFile += ".pdf";
                }

                if (!Directory.Exists(Path.GetDirectoryName(strSaveFile)) || !Utils.CanWriteToPath(strSaveFile))
                {
                    Program.MainForm.ShowMessageBox(this,
                                                    string.Format(GlobalSettings.CultureInfo,
                                                                  await LanguageManager.GetStringAsync(
                                                                      "Message_File_Cannot_Be_Accessed"), strSaveFile));
                    return;
                }

                if (!await Utils.SafeDeleteFileAsync(strSaveFile, true))
                {
                    Program.MainForm.ShowMessageBox(this,
                                                    string.Format(GlobalSettings.CultureInfo,
                                                                  await LanguageManager.GetStringAsync(
                                                                      "Message_File_Cannot_Be_Accessed"), strSaveFile));
                    return;
                }

                // No PDF printer found, let's use wkhtmltopdf

                try
                {
                    PdfDocument objPdfDocument = new PdfDocument
                    {
                        Html        = webViewer.DocumentText,
                        ExtraParams = new Dictionary <string, string>(8)
                        {
                            { "encoding", "UTF-8" },
                            { "dpi", "300" },
                            { "margin-top", "13" },
                            { "margin-bottom", "19" },
                            { "margin-left", "13" },
                            { "margin-right", "13" },
                            { "image-quality", "100" },
                            { "print-media-type", string.Empty }
                        }
                    };
                    PdfConvertEnvironment objPdfConvertEnvironment = new PdfConvertEnvironment
                    {
                        WkHtmlToPdfPath = Path.Combine(Utils.GetStartupPath, "wkhtmltopdf.exe")
                    };
                    PdfOutput objPdfOutput = new PdfOutput {
                        OutputFilePath = strSaveFile
                    };
                    await PdfConvert.ConvertHtmlToPdfAsync(objPdfDocument, objPdfConvertEnvironment, objPdfOutput);

                    if (!string.IsNullOrWhiteSpace(GlobalSettings.PdfAppPath))
                    {
                        Uri    uriPath   = new Uri(strSaveFile);
                        string strParams = GlobalSettings.PdfParameters
                                           .Replace("{page}", "1")
                                           .Replace("{localpath}", uriPath.LocalPath)
                                           .Replace("{absolutepath}", uriPath.AbsolutePath);
                        ProcessStartInfo objPdfProgramProcess = new ProcessStartInfo
                        {
                            FileName    = GlobalSettings.PdfAppPath,
                            Arguments   = strParams,
                            WindowStyle = ProcessWindowStyle.Hidden
                        };
                        objPdfProgramProcess.Start();
                    }
                }
                catch (Exception ex)
                {
                    Program.MainForm.ShowMessageBox(this, ex.ToString());
                }
            }
        }
Example #10
0
        public PdfOutput ExtractPdf(string pdfFile)
        {
            string     pdfPath   = Path.Combine(hostingEnvironment.WebRootPath, pdfFile.Replace("wwwroot", "").Substring(1).Replace("/", "\\"));
            FileStream docStream = new FileStream(pdfPath, FileMode.Open, FileAccess.Read);
            PdfOutput  output    = new PdfOutput()
            {
                Data = new List <TableData>()
            };

            FixedDocument doc = new FixedDocument(docStream);

            string extractedTexts = doc.Pages[0].ExtractText(Apitron.PDF.Kit.Extraction.TextExtractionOptions.FormattedText);

            string[] rows = extractedTexts.Split("\r\n");

            for (int i = 0; i < rows.Length; i++)
            {
                if (rows[i].Contains("Kaartnummer") && rows[i].Contains("Datum") && rows[i].Contains("maandafrekening"))
                {
                    output.Name = Regex.Match(rows[i + 1], "([A-Z]+[ ]*)+").Value;
                    output.Date = Regex.Match(rows[i + 1], "(0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])[- /.]([0-9]{2})").Value;
                    i++;
                    continue;
                }
                if (rows[i].Contains("Vorigsaldo") && rows[i].Contains("Tebetalen"))
                {
                    var matches = Regex.Match(rows[i + 1], @"\d{1,3}(\.\d{3})*(,\d{2})");
                    output.StartBalance = matches.Value;

                    var tempMatch = matches;
                    while (matches.Success)
                    {
                        tempMatch = matches;
                        matches   = matches.NextMatch();
                    }

                    output.FinalBalance = tempMatch.Value;
                    i++;
                    continue;
                }
                if (rows[i].Contains("Periode:"))
                {
                    output.Period = Regex.Match(rows[i], @"(\d+[a-z ]*)+").Value.Replace("tot", "tot ");
                    break;
                }
            }

            output.Data.AddRange(rows.Where(r => Regex.IsMatch(r, @"((\d{1,2})+[a-z]{3})") && Regex.IsMatch(r, @"\d{1,3}(\.\d{3})*(,\d{2})"))
                                 .Select((r) => new TableData
            {
                Amount          = Regex.Match(r, @"\d{1,3}(\.\d{3})*(,\d{2})").Value,
                ForigenAmount   = Regex.Match(r, @"\d{1,3}(\,\d{3})*([.]\d{2})").Value,
                ProccessDate    = Regex.Match(r, @"((\d{1,2})+[a-z]{3})").NextMatch().Value,
                TransactionDate = Regex.Match(r, @"((\d{1,2})+[a-z]{3})").Value,
                TransactionData = Regex.Replace(Regex.Replace(Regex.Replace(r, @"\d{1,3}(\.\d{3})*(,\d{2})", ""), @"\d{1,3}(\,\d{3})*([.]\d{2})", ""), @"((\d{1,2})+[a-z]{3})", ""),
                ForigenDetail   = rows.Length - 1 >= rows.IndexOf(r) + 2 ? Regex.Match(rows[rows.IndexOf(r) + 1].Replace(" ", ""), "^[A-Za-z]+").Value : "",
                DataDetail      = rows.Length - 1 >= rows.IndexOf(r) + 2 ? Regex.Match(rows[rows.IndexOf(r) + 2].Replace(" ", ""), @"^[A-Z]{2,}[A-Za-z\d.+,]*").Value : ""
            }));
            for (int i = 1; i < doc.Pages.Count; i++)
            {
                //Extract text from first page.
                extractedTexts = doc.Pages[i].ExtractText(Apitron.PDF.Kit.Extraction.TextExtractionOptions.FormattedText);
                rows           = extractedTexts.Split("\r\n");

                output.Data.AddRange(rows.Where(r => Regex.IsMatch(r, @"((\d{1,2})+[a-z]{3})") && Regex.IsMatch(r, @"\d{1,3}(\.\d{3})*(,\d{2})"))
                                     .Select((r) => new TableData
                {
                    Amount          = Regex.Match(r, @"\d{1,3}(\.\d{3})*(,\d{2})").Value,
                    ForigenAmount   = Regex.Match(r, @"\d{1,3}(\,\d{3})*([.]\d{2})").Value,
                    ProccessDate    = Regex.Match(r, @"((\d{1,2})+[a-z]{3})").NextMatch().Value,
                    TransactionDate = Regex.Match(r, @"((\d{1,2})+[a-z]{3})").Value,
                    TransactionData = Regex.Replace(Regex.Replace(Regex.Replace(r, @"\d{1,3}(\.\d{3})*(,\d{2})", ""), @"\d{1,3}(\,\d{3})*([.]\d{2})", ""), @"((\d{1,2})+[a-z]{3})", ""),
                    ForigenDetail   = rows.Length - 1 >= rows.IndexOf(r) + 2 ? Regex.Match(rows[rows.IndexOf(r) + 1].Replace(" ", ""), "^[A-Za-z]+").Value : "",
                    DataDetail      = rows.Length - 1 >= rows.IndexOf(r) + 2? Regex.Match(rows[rows.IndexOf(r) + 2].Replace(" ", ""), @"^[A-Z]{2,}[A-Za-z\d.+,]*").Value:""
                }));
            }

            doc.Dispose();

            docStream.Close();
            File.Delete(pdfPath);
            return(output);
        }
Example #11
0
        public static ResponseStatusMessage GenerateDocument(PdfDocument pdfDocument, PdfOutput pdfOutput)
        {
            ResponseStatusMessage responseStatusMessage = new ResponseStatusMessage();

            try
            {
                Console.InputEncoding = Encoding.UTF8;
                Environment.Debug     = false;
                ConvertHtmlToPdfCustom(pdfDocument, pdfOutput);
                responseStatusMessage.Status = "Success";
            }
            catch (Exception ex)
            {
                responseStatusMessage.Status = "Failure";
                responseStatusMessage.ErrorMessage.Add(ex.Message);
            }
            return(responseStatusMessage);
        }
Example #12
0
        public static void ConvertHtmlToPdfCustom(PdfDocument document, PdfConvertEnvironment environment, PdfOutput woutput)
        {
            if (environment == null)
            {
                environment = Environment;
            }

            if (document.Html != null)
            {
                document.Url = "-";
            }

            String outputPdfFilePath;
            bool   delete;

            if (woutput.OutputFilePath != null)
            {
                outputPdfFilePath = woutput.OutputFilePath;
                delete            = false;
            }
            else
            {
                outputPdfFilePath = Path.Combine(environment.TempFolderPath, String.Format("{0}.pdf", Guid.NewGuid()));
                delete            = true;
            }

            if (!File.Exists(environment.WkHtmlToPdfPath))
            {
                throw new PdfConvertException(String.Format("File '{0}' not found. Check if wkhtmltopdf application is installed.", environment.WkHtmlToPdfPath));
            }

            StringBuilder paramsBuilder = new StringBuilder();

            //if (String.IsNullOrEmpty(document.PaperType))
            //    document.PaperType = PaperTypes.A4;
            //paramsBuilder.AppendFormat("--page-size {0} ", document.PaperType);

            if (!string.IsNullOrEmpty(document.HeaderUrl))
            {
                paramsBuilder.AppendFormat("--header-html {0} ", document.HeaderUrl);
            }
            if (!string.IsNullOrEmpty(document.FooterUrl))
            {
                paramsBuilder.AppendFormat("--footer-html {0} ", document.FooterUrl);
            }
            if (!string.IsNullOrEmpty(document.JWTToken))
            {
                string cookieData = ".AspNetCore.Antiforgery.5uYu5VgZzcE=" + document.AntiForgeryToken
                                    + ";JWTToken=" + document.JWTToken
                                    + ";.AspNetCore.Cookies=" + document.CookiesToken;
                paramsBuilder.AppendFormat("--custom-header Cookie \"{0}\" ", cookieData);
            }

            paramsBuilder.AppendFormat("--debug-javascript ");
            paramsBuilder.AppendFormat("--no-custom-header-propagation ");

            /*-B, --margin-bottom <unitreal>      Set the page bottom margin
             * -L, --margin-left <unitreal>        Set the page left margin (default 10mm)
             * -R, --margin-right <unitreal>       Set the page right margin (default 10mm)
             * -T, --margin-top <unitreal> */

            if (document.ExtraParams != null)
            {
                foreach (var extraParam in document.ExtraParams)
                {
                    paramsBuilder.AppendFormat("--{0} {1} ", extraParam.Key, extraParam.Value);
                }
            }

            if (document.Cookies != null)
            {
                foreach (var cookie in document.Cookies)
                {
                    paramsBuilder.AppendFormat("--cookie {0} {1} ", cookie.Key, cookie.Value);
                }
            }

            paramsBuilder.AppendFormat("\"{0}\" \"{1}\"", document.Url, outputPdfFilePath);

            try
            {
                StringBuilder output = new StringBuilder();
                StringBuilder error  = new StringBuilder();

                using (Process process = new Process())
                {
                    process.StartInfo.FileName               = environment.WkHtmlToPdfPath;
                    process.StartInfo.Arguments              = paramsBuilder.ToString();
                    process.StartInfo.UseShellExecute        = false;
                    process.StartInfo.RedirectStandardOutput = true;
                    process.StartInfo.RedirectStandardError  = true;
                    process.StartInfo.RedirectStandardInput  = true;

                    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
                        using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
                        {
                            DataReceivedEventHandler outputHandler = (sender, e) =>
                            {
                                if (e.Data == null)
                                {
                                    outputWaitHandle.Set();
                                }
                                else
                                {
                                    output.AppendLine(e.Data);
                                }
                            };

                            DataReceivedEventHandler errorHandler = (sender, e) =>
                            {
                                if (e.Data == null)
                                {
                                    errorWaitHandle.Set();
                                }
                                else
                                {
                                    error.AppendLine(e.Data);
                                }
                            };

                            process.OutputDataReceived += outputHandler;
                            process.ErrorDataReceived  += errorHandler;

                            try
                            {
                                process.Start();

                                process.BeginOutputReadLine();
                                process.BeginErrorReadLine();

                                if (document.Html != null)
                                {
                                    using (var stream = process.StandardInput)
                                    {
                                        byte[] buffer = Encoding.UTF8.GetBytes(document.Html);
                                        stream.BaseStream.Write(buffer, 0, buffer.Length);
                                        stream.WriteLine();
                                    }
                                }

                                if (process.WaitForExit(environment.Timeout) && outputWaitHandle.WaitOne(environment.Timeout) && errorWaitHandle.WaitOne(environment.Timeout))
                                {
                                    if (process.ExitCode != 0 && !File.Exists(outputPdfFilePath))
                                    {
                                        throw new PdfConvertException(String.Format("Html to PDF conversion of '{0}' failed. Wkhtmltopdf output: \r\n{1}", document.Url, error));
                                    }
                                }
                                else
                                {
                                    if (!process.HasExited)
                                    {
                                        process.Kill();
                                    }

                                    throw new PdfConvertTimeoutException();
                                }
                            }
                            finally
                            {
                                process.OutputDataReceived -= outputHandler;
                                process.ErrorDataReceived  -= errorHandler;
                            }
                        }
                }


                if (woutput.OutputStream != null)
                {
                    using (Stream fs = new FileStream(outputPdfFilePath, FileMode.Open))
                    {
                        byte[] buffer = new byte[32 * 1024];
                        int    read;

                        while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            woutput.OutputStream.Write(buffer, 0, read);
                        }
                    }
                }

                if (woutput.OutputCallback != null)
                {
                    byte[] pdfFileBytes = File.ReadAllBytes(outputPdfFilePath);
                    woutput.OutputCallback(document, pdfFileBytes);
                }
            }
            finally
            {
                if (delete && File.Exists(outputPdfFilePath))
                {
                    File.Delete(outputPdfFilePath);
                }
            }
        }