是否可以从任何html文件中获取wkhtmltopdf创建的pdf流,并在IE / Firefox / Chrome等中弹出下载对话框?
目前我通过此代码获取输出流:
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);
}
}
}
然后我想显示对话框:
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();
使用从PDF文件创建的MemoryStream可以正常工作,但在这里我只得到一个空页面。 bytearray有1270字节。
答案 0 :(得分:4)
这还是个问题吗?
我刚刚创建了一个新的ASP.net网站,在安装了wkhtmltopdf 0.11.0 rc2之后在我的计算机上测试了这个,并且它可以很好地创建PDF。我的版本略有不同;
在我的CSHTML中,我有:
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();
我的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);
}
}
}
答案 1 :(得分:0)
基于@Nenotlep的回答,我对此持怀疑态度。这只是pdf生成部分。
我正在使用异步。我创建了一个新的StreamWriter,因为wkhtmltopdf默认情况下期望utf-8,但在过程开始时将其设置为其他值。
我删除了p.WaitForExit(...),因为如果它失败我将无法处理,并且无论如何它会挂在await tStandardOutput
上。如果需要超时,那么您必须调用带有取消令牌或超时的其他任务上的等待,并相应地进行处理。
public static async Task<byte[]> GeneratePdf(string html, Size pageSize)
{
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = @"C:\PROGRA~1\WKHTML~1\wkhtmltopdf.exe",
UseShellExecute = false,
CreateNoWindow = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
Arguments = "-q -n --disable-smart-shrinking "
+ (pageSize.IsEmpty ? "" : "--page-width " + pageSize.Width
+ "mm --page-height " + pageSize.Height + "mm") + " - -";
};
using (var p = Process.Start(psi))
using (var pdfSream = new MemoryStream())
using (var utf8Writer = new StreamWriter(p.StandardInput.BaseStream,
Encoding.UTF8))
{
await utf8Writer.WriteAsync(html);
utf8Writer.Close();
var tStdOut = p.StandardOutput.BaseStream.CopyToAsync(pdfSream);
var tStdError = p.StandardError.ReadToEndAsync();
await tStandardOutput;
string errors = await tStandardError;
if (!string.IsNullOrEmpty(errors))
{
//deal with errors
}
return pdfSream.ToArray();
}
}
我没有包含在其中的东西,但可以作为参考: