2012-04-24 18 views
6

¿es posible obtener un flujo de pdf creado por wkhtmltopdf desde cualquier archivo html y abrir un cuadro de diálogo de descarga en IE/Firefox/Chrome, etc.?wkhtmltopdf outputstream & download - diaglog

Por el momento tengo mi OutputStream por este código:

public class Printer 
{ 
    public static MemoryStream GeneratePdf(StreamReader Html, MemoryStream pdf, Size pageSize) 
    { 
     Process p; 
     StreamWriter stdin; 
     ProcessStartInfo psi = new ProcessStartInfo(); 

     psi.FileName = @"C:\PROGRA~1\WKHTML~1\wkhtmltopdf.exe"; 

     // run the conversion utility 
     psi.UseShellExecute = false; 
     psi.CreateNoWindow = true; 
     psi.RedirectStandardInput = true; 
     psi.RedirectStandardOutput = true; 
     psi.RedirectStandardError = true; 

     // note that we tell wkhtmltopdf to be quiet and not run scripts 
     psi.Arguments = "-q -n --disable-smart-shrinking " + (pageSize.IsEmpty ? "" : "--page-width " + pageSize.Width + "mm --page-height " + pageSize.Height + "mm") + " - -"; 

     p = Process.Start(psi); 

     try 
     { 
      stdin = p.StandardInput; 
      stdin.AutoFlush = true; 
      stdin.Write(Html.ReadToEnd()); 
      stdin.Dispose(); 

      CopyStream(p.StandardOutput.BaseStream, pdf); 
      p.StandardOutput.Close(); 
      pdf.Position = 0; 

      p.WaitForExit(10000); 

      return pdf; 
     } 
     catch 
     { 
      return null; 
     } 
     finally 
     { 
      p.Dispose(); 
     } 
    } 

    public static void CopyStream(Stream input, Stream output) 
    { 
     byte[] buffer = new byte[32768]; 
     int read; 
     while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
     { 
      output.Write(buffer, 0, read); 
     } 
    } 
} 

entonces quiero mostrar el diálogo:

MemoryStream PDF = Printer.GeneratePdf(Rd, PDFStream, Size); 

byte[] byteArray1 = PDF.ToArray(); 
PDF.Flush(); 
PDF.Close(); 
Response.BufferOutput = true; 

Response.Clear(); 
Response.ClearHeaders(); 
Response.AddHeader("Content-Disposition", "attachment; filename=Test.pdf"); 
Response.ContentType = "application/octet-stream"; 
Response.BinaryWrite(byteArray1); 
Response.End(); 

Con MemoryStreams creados a partir de un archivo PDF esto funciona bien, pero aquí Solo tengo una página vacía. El bytearray tiene 1270 Bytes.

+0

Quizás quiso solucionar este problema? ¿Ayudó mi solución? – Nenotlep

Respuesta

3

¿Esto todavía es un problema?

Acabo de crear un nuevo sitio web ASP.net para probar esto en mi computadora después de instalar wkhtmltopdf 0.11.0 rc2 y funcionó bien al crear el PDF. Mi versión era solo un poco diferente;

En mi CSHTML tuve:

MemoryStream PDFStream = new MemoryStream(); 
MemoryStream PDF = Derp.GeneratePdf(PDFStream); 
byte[] byteArray1 = PDF.ToArray(); 
PDF.Flush(); 
PDF.Close(); 
Response.BufferOutput = true; 
Response.Clear(); 
Response.ClearHeaders(); 
Response.AddHeader("Content-Disposition", "attachment; filename=Test.pdf"); 
Response.ContentType = "application/octet-stream"; 
Response.BinaryWrite(byteArray1); 
Response.End(); 

Mi clase Derp

public class Derp 
{ 
    public static MemoryStream GeneratePdf(MemoryStream pdf) 
    { 
     using (StreamReader Html = new StreamReader(@"Z:\HTMLPage.htm")) 
     { 
      Process p; 
      StreamWriter stdin; 
      ProcessStartInfo psi = new ProcessStartInfo(); 
      psi.FileName = @"C:\wkhtmltopdf\wkhtmltopdf.exe"; 
      psi.UseShellExecute = false; 
      psi.CreateNoWindow = true; 
      psi.RedirectStandardInput = true; 
      psi.RedirectStandardOutput = true; 
      psi.RedirectStandardError = true; 
      psi.Arguments = "-q -n --disable-smart-shrinking " + " - -"; 
      p = Process.Start(psi); 
      try 
      { 
       stdin = p.StandardInput; 
       stdin.AutoFlush = true; 
       stdin.Write(Html.ReadToEnd()); 
       stdin.Dispose(); 
       CopyStream(p.StandardOutput.BaseStream, pdf); 
       p.StandardOutput.Close(); 
       pdf.Position = 0; 
       p.WaitForExit(10000); 
       return pdf; 
      } 
      catch 
      { 
       return null; 
      } 
      finally 
      { 
       p.Dispose(); 
      } 
     } 
    } 

    public static void CopyStream(Stream input, Stream output) 
    { 
     byte[] buffer = new byte[32768]; 
     int read; 
     while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
     { 
      output.Write(buffer, 0, read); 
     } 
    } 
} 
+0

Por lo tanto, si tiene problemas con el resultado, es posible que desee comprobar cómo obtiene el código fuente HTML para el convertidor si tiene algún problema. – Nenotlep

+0

¿Cuál es el + "- -"; porque al final de tus argumentos? –

+1

@Mvision He concatenado de forma estúpida, pero significa que en lugar de archivos para entrada y salida, utilizaré flujos como entrada y salida. Por ejemplo, para obtener wkhtmltopdf para obtener su entrada de STDIN en lugar de un archivo o URL y enviarla a un archivo, usará 'wkhtmltopdf.exe - output.pdf'. De manera similar, para usar un archivo de entrada y enviarlo a STDOUT (o tal vez a stderr, no lo recuerdo), usaría 'wkhtmltopdf.exe input.html -' – Nenotlep