初始转换后挂起 TuesPechkin
Hanging TuesPechkin after initial conversion
我正在尝试创建一个可以将样式化的 HTML 文件转换为 PDF 的 Web API。
我正在使用 TuesPechkin 并将我的应用程序安装到 IIS 中(作为 32 位应用程序:我已将应用程序池修改为 运行 32 位模式)。
IIS 8.5 运行正在 Windows Server 2012 R2 上运行。
C# 中的 PDFConversion class:
using System.Drawing.Printing;
using System.IO;
using TuesPechkin;
namespace PDFApi
{
public class PDFcreator
{
public void convert(string path, string uri)
{
IConverter converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDelpoyment())));
var document = new HtmlToPdfDocument
{
GlobalSettings =
{
ProduceOutline = true,
DocumentTitle = "Converted Form",
PaperSize = PaperKind.A4,
Margins =
{
All = 1.375,
Unit = Unit.Centimeters
}
},
Objects =
{
new ObjectSettings { RawData = File.ReadAllBytes(uri) }
}
};
byte[] pdfBuf = converter.Convert(document);
FileStream fs = new FileStream(path, FileMode.Create);
fs.Write(pdfBuf, 0, pdfBuf.Length);
fs.Close();
}
}
}
控制器如下:
[Route("converthtml")]
[HttpPost]
[MIMEContentFilter]
public async Task<HttpResponseMessage> ConvertHtml()
{
string temppath = System.IO.Path.GetTempPath();
var streamProvider = new MultipartFormDataStreamProvider(temppath);
await Request.Content.ReadAsMultipartAsync(streamProvider);
string filepath = streamProvider.FileData.Select(entry => entry.LocalFileName.Replace(temppath + "\", "")).First<string>();
string pdfpath = System.IO.Path.GetTempFileName();
pdfpath = pdfpath.Substring(0, pdfpath.LastIndexOf('.')) + ".pdf";
new PDFcreator().convert(pdfpath, filepath);
var stream = new FileStream(pdfpath, FileMode.Open);
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return result;
}
这里有点奇怪:在 Fiddler 中进行试验,发送一次文件将立即 return PDF。但是,所有后续 POST 都会让 Fiddler 挂起。
检查任务管理器显示此任务的 CPU 和内存分别跳升至 13.5% 和 ~96MB。
Temp 文件夹(存储文件的地方)在成功 运行 时将包含三个文件:原始上传文件(以类似 GUID 的名称存储)、通过生成的文件wkHtmlToPdf(格式为 "wktemp-"),以及生成的 pdf(格式为 tempXXXX.pdf)。
在它挂起的情况下,只能找到第一个文件,说明问题出在wkHtmlToPdf本身的某个地方。
然而,真正的问题是在任务管理器中手动终止进程时,API 成功完成,returns pdf,完全创建!
如果IIS被重置,进程returns回到原来的状态;新的尝试将没有问题。
显然,在每次调用后重置 IIS 几乎不可行,每次手动终止进程也不可行...
这是一个错误吗/这个问题有什么解决方案吗?
看来您使用的是 64 位的 WkHtmlToPdf,并且您已经安装了 32 位的。
你应该改变:
IConverter converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDelpoyment())));
至
IConverter converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win32EmbeddedDeployment(
new TempFolderDelpoyment())));
var tempFolderDeployment = new TempFolderDeployment();
var win32EmbeddedDeployment = new Win32EmbeddedDeployment(tempFolderDeployment);
var remotingToolset = new RemotingToolset<PdfToolset>(win32EmbeddedDeployment);
var converter =
new ThreadSafeConverter(remotingToolset);
byte[] pdfBuf = converter.Convert(document);
remotingToolset.Unload();
卸载 remotingToolset 将防止挂起
RemotingToolset.Unload();
非常重要-
@toshkata-tonev 的回答对我有帮助,但是当很多会话使用此功能时,我们的服务器崩溃了,因为 CPU!
重点是该进程应该作为静态共享函数由所有会话共享。
所以这就是我的解决方案:
实施:
在您的应用程序中创建静态 class:
public static class TuesPechkinInitializerService {
private static string staticDeploymentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wkhtmltopdf");
public static void CreateWkhtmltopdfPath()
{
if (Directory.Exists(staticDeploymentPath) == false)
{
Directory.CreateDirectory(staticDeploymentPath);
}
}
public static IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new StaticDeployment(staticDeploymentPath)
)
)
);
}
在 GLOBAL.asax 中,我在项目开始时初始化 class:
TuesPechkinInitializerService.CreateWkhtmltopdfPath();
并使用它:
HtmlToPdfDocument pdfDocument = new HtmlToPdfDocument
{
GlobalSettings = new GlobalSettings(),
Objects =
{
new ObjectSettings
{
ProduceLocalLinks = true,
ProduceForms = true,
HtmlText = htmlContent
}
}
};
byte[] pdfDocumentData = TuesPechkinInitializerService.converter.Convert(pdfDocument);
感谢:
我正在尝试创建一个可以将样式化的 HTML 文件转换为 PDF 的 Web API。
我正在使用 TuesPechkin 并将我的应用程序安装到 IIS 中(作为 32 位应用程序:我已将应用程序池修改为 运行 32 位模式)。
IIS 8.5 运行正在 Windows Server 2012 R2 上运行。
C# 中的 PDFConversion class:
using System.Drawing.Printing;
using System.IO;
using TuesPechkin;
namespace PDFApi
{
public class PDFcreator
{
public void convert(string path, string uri)
{
IConverter converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDelpoyment())));
var document = new HtmlToPdfDocument
{
GlobalSettings =
{
ProduceOutline = true,
DocumentTitle = "Converted Form",
PaperSize = PaperKind.A4,
Margins =
{
All = 1.375,
Unit = Unit.Centimeters
}
},
Objects =
{
new ObjectSettings { RawData = File.ReadAllBytes(uri) }
}
};
byte[] pdfBuf = converter.Convert(document);
FileStream fs = new FileStream(path, FileMode.Create);
fs.Write(pdfBuf, 0, pdfBuf.Length);
fs.Close();
}
}
}
控制器如下:
[Route("converthtml")]
[HttpPost]
[MIMEContentFilter]
public async Task<HttpResponseMessage> ConvertHtml()
{
string temppath = System.IO.Path.GetTempPath();
var streamProvider = new MultipartFormDataStreamProvider(temppath);
await Request.Content.ReadAsMultipartAsync(streamProvider);
string filepath = streamProvider.FileData.Select(entry => entry.LocalFileName.Replace(temppath + "\", "")).First<string>();
string pdfpath = System.IO.Path.GetTempFileName();
pdfpath = pdfpath.Substring(0, pdfpath.LastIndexOf('.')) + ".pdf";
new PDFcreator().convert(pdfpath, filepath);
var stream = new FileStream(pdfpath, FileMode.Open);
var result = new HttpResponseMessage(HttpStatusCode.OK);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return result;
}
这里有点奇怪:在 Fiddler 中进行试验,发送一次文件将立即 return PDF。但是,所有后续 POST 都会让 Fiddler 挂起。 检查任务管理器显示此任务的 CPU 和内存分别跳升至 13.5% 和 ~96MB。
Temp 文件夹(存储文件的地方)在成功 运行 时将包含三个文件:原始上传文件(以类似 GUID 的名称存储)、通过生成的文件wkHtmlToPdf(格式为 "wktemp-"),以及生成的 pdf(格式为 tempXXXX.pdf)。 在它挂起的情况下,只能找到第一个文件,说明问题出在wkHtmlToPdf本身的某个地方。
然而,真正的问题是在任务管理器中手动终止进程时,API 成功完成,returns pdf,完全创建!
如果IIS被重置,进程returns回到原来的状态;新的尝试将没有问题。
显然,在每次调用后重置 IIS 几乎不可行,每次手动终止进程也不可行...
这是一个错误吗/这个问题有什么解决方案吗?
看来您使用的是 64 位的 WkHtmlToPdf,并且您已经安装了 32 位的。
你应该改变:
IConverter converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new TempFolderDelpoyment())));
至
IConverter converter = new StandardConverter(
new RemotingToolset<PdfToolset>(
new Win32EmbeddedDeployment(
new TempFolderDelpoyment())));
var tempFolderDeployment = new TempFolderDeployment();
var win32EmbeddedDeployment = new Win32EmbeddedDeployment(tempFolderDeployment);
var remotingToolset = new RemotingToolset<PdfToolset>(win32EmbeddedDeployment);
var converter =
new ThreadSafeConverter(remotingToolset);
byte[] pdfBuf = converter.Convert(document);
remotingToolset.Unload();
卸载 remotingToolset 将防止挂起
RemotingToolset.Unload();
非常重要-
@toshkata-tonev 的回答对我有帮助,但是当很多会话使用此功能时,我们的服务器崩溃了,因为 CPU!
重点是该进程应该作为静态共享函数由所有会话共享。
所以这就是我的解决方案:
实施: 在您的应用程序中创建静态 class:
public static class TuesPechkinInitializerService {
private static string staticDeploymentPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wkhtmltopdf");
public static void CreateWkhtmltopdfPath()
{
if (Directory.Exists(staticDeploymentPath) == false)
{
Directory.CreateDirectory(staticDeploymentPath);
}
}
public static IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win64EmbeddedDeployment(
new StaticDeployment(staticDeploymentPath)
)
)
);
}
在 GLOBAL.asax 中,我在项目开始时初始化 class:
TuesPechkinInitializerService.CreateWkhtmltopdfPath();
并使用它:
HtmlToPdfDocument pdfDocument = new HtmlToPdfDocument
{
GlobalSettings = new GlobalSettings(),
Objects =
{
new ObjectSettings
{
ProduceLocalLinks = true,
ProduceForms = true,
HtmlText = htmlContent
}
}
};
byte[] pdfDocumentData = TuesPechkinInitializerService.converter.Convert(pdfDocument);
感谢: