c# - 尝试从缓冲区读取字节到 int 时进程挂起。wkhtmltopdf
问题描述
我的方法使用Wkhtmltopdf
带有Process
. 我找不到它挂起的原因。当有一个带有 HTML 的大字符串时,我想当有 30 页或更多页面时它会挂起。但是,如果页面较少,一切正常。我可以看到 Wkhtmltopdf.exe 进程Task Manager
,它不会永远退出。hanged
当我用Wkhtmltopdf停止我的 MVC 项目时, it creates normally
PDF 就像它会等待一些东西。当然,手动地,Wkhtmltopdf 可以毫无问题地创建所有内容。这不是这篇文章的重复。这里我在尝试将字节读入 int 时遇到问题。
public IActionResult createPdf()
{
string html = "content";
Process p;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "...\\wkhtmltopdf.exe";
psi.WorkingDirectory = "...\\wkhtmltopdf\\bin";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.StandardOutputEncoding = System.Text.Encoding.UTF8;
psi.Arguments = "-O landscape --footer-left qwe --footer-center [page]/[topage] --footer-right --footer-font-size 9 --no-stop-slow-scripts --zoom 0.8 --dpi 300 - - ";
p = Process.Start(psi);
byte[] pdf = null;
try
{
// Get PDF as bytes without temp files
using(StreamWriter stdin = new StreamWriter(p.StandardInput.BaseStream, Encoding.UTF8))
{
stdin.AutoFlush = true;
stdin.Write(html);
}
byte[] buffer = new byte[32768];
using(var ms = new MemoryStream())
{
while(true)
{
// HANGS HERE!!!
int read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
if(read <= 0)
{
break;
}
ms.Write(buffer, 0, read);
}
pdf = ms.ToArray();
}
}
...
}
解决方案
我设法通过使用PdfSharp将分离的pdf 文件合并为一个来解决这个问题,而不是将连接的内容作为一个传递。它持续时间更长一点,但至少它有效。除了库(如果您像我一样使用 MVC,则排除版本警告),您可能需要安装以排除可能导致的编码错误。我的方法不使用临时文件,只使用字节,最后它将创建的 pdf 发送到浏览器。wkhtmltopdf
PdfSharp
PdfSharp.Core
System.Text.Encoding.CodePages
PdfSharp
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
public IActionResult createPdf()
{
string html = "";
byte[] pdf = null;
using(PdfDocument doc = new PdfDocument())
{
for(int i = 0; i < files.Length; i++)
{
html = "html content";
Process p;
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "...\\wkhtmltopdf.exe";
psi.WorkingDirectory = "...\\wkhtmltopdf\\bin";
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.StandardOutputEncoding = System.Text.Encoding.UTF8;
psi.Arguments = "-O landscape --footer-left qwe --footer-center [page]/[topage] --footer-right --footer-font-size 9 --no-stop-slow-scripts --zoom 0.8 --dpi 300 - - ";
p = Process.Start(psi);
using(StreamWriter stdin = new StreamWriter(p.StandardInput.BaseStream, Encoding.UTF8))
{
stdin.AutoFlush = true;
stdin.Write(html);
}
byte[] buffer = new byte[32768];
byte[] currentPdf = null;
using(var ms = new MemoryStream())
{
while(true)
{
int read = p.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length);
if(read <= 0)
{
break;
}
ms.Write(buffer, 0, read);
}
currentPdf = ms.ToArray();
}
p.StandardOutput.Close();
p.WaitForExit(10000);
p.Close();
MemoryStream currentPDF = new MemoryStream(currentPdf);
// Merge separated pdfs into one
// Solves encoding errors
System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
using(PdfDocument pdfDoc = PdfReader.Open(currentPDF, PdfDocumentOpenMode.Import))
{
for(int j = 0; j < pdfDoc.PageCount; j++)
{
doc.AddPage(pdfDoc.Pages[j]);
}
}
currentPDF.Close();
}
// Get merged pdfs as bytes
MemoryStream rms = new MemoryStream();
doc.Save(rms, false);
pdf = rms.ToArray();
rms.Close();
}
MemoryStream PDF = new MemoryStream(pdf);
// Return PDF to browser
return new FileStreamResult(PDF, "application/x-msdownload")
{
FileDownloadName = "mergedPdfs.pdf"
};
}
推荐阅读
- java - do-while 循环只能与布尔变量一起运行吗?爪哇
- asynchronous - 在 Task.Delay() 中将元素添加到 XAML 页面
- mysql - 在 docker-compose 中使用 MySQL 初始化 Hibernate 时连接被拒绝
- graphics - 将我的头包裹在对象到世界坐标的转换上
- javascript - 在反应中添加子时更新父中的数据
- java - 改进 Intellij 代码检查以防止可能产生 NullPointerException 警告
- javascript - 错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。在 App.js 中使用 react-hook-form 时出错
- android - 如何监听状态属性变化 Flutter bloc 模式
- python - 您能以编程方式获取 cdk 资源的 ARN 或物理名称吗?
- git - 如何显示 git log 和 git diff 中每个文件添加和删除的行数?