Изображения не отображаются в PDF
У меня довольно простая HTML-страница, отображаемая через asp.net. Это выглядит красиво в PDF после запуска его через HtmlRenderer.PdfSharp, ЗА ИСКЛЮЧЕНИЕМ, что изображения не появляются. Только красный X отсутствующего изображения в PDF, даже если сама веб-страница отображает изображение правильно.
Вот мой код HtmlRenderer.PdfSharp:
public void BuildPDF( string url, string pdfPath ) {
string html = GetHTML(url);
Byte[] res = null;
using( MemoryStream ms = new MemoryStream() ) {
using( FileStream file = new FileStream(pdfPath, FileMode.Create, FileAccess.Write) ) {
byte[] bytes = new byte[ms.Length];
var pdf = TheArtOfDev.HtmlRenderer.PdfSharp.PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
pdf.Save(ms);
res = ms.ToArray();
file.Write(res, 0, res.Length);
ms.Close();
}
}
}
private string GetHTML(string url) {
string html = string.Empty;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.AutomaticDecompression = DecompressionMethods.GZip;
using( HttpWebResponse response = (HttpWebResponse)request.GetResponse() )
using( Stream stream = response.GetResponseStream() )
using( StreamReader reader = new StreamReader(stream) ) {
html = reader.ReadToEnd();
}
return html;
}
И вот HTML-код img, который не отображается в PDF: <img src="images/ChartImg.png" />
Как я могу решить это?
3 ответа
Используйте абсолютный путь к изображениям.
<img src="http://example.org/images/ChartImg.png" />
Вы можете проанализировать html и сначала заменить строку, прежде чем передавать ее в pdf конвертер.
Код ниже :
var pdf = PdfGenerator.GeneratePdf(Html, PageSize.A4, 20, null, OnStylesheetLoad, OnImageLoadPdfSharp);
... ...
public static void OnImageLoadPdfSharp(object sender, HtmlImageLoadEventArgs e)
{
var url = e.Src;
if (!e.Src.StartsWith("http://") && !e.Src.StartsWith("https://"))
{
var ImgFilePath = System.Web.HttpContext.Current.Server.MapPath(url);
if (XImage.ExistsFile(ImgFilePath))
e.Callback(XImage.FromFile(ImgFilePath));
var ImgFilePath2 = System.Web.HttpContext.Current.Server.MapPath(url);
if (XImage.ExistsFile(ImgFilePath2))
e.Callback(XImage.FromFile(ImgFilePath2));
}
else
{
using (var client = new WebClient())
{
using (var stream = new MemoryStream(client.DownloadData(url)))
{
e.Callback(XImage.FromStream(stream));
}
}
}
}
Для этого лучше использовать обратный вызов разрешения изображения:
var pdf = PdfGenerator.GeneratePdf(html, pdfConfig, imageLoad: OnImageLoad);
// snip
private void OnImageLoad(object sender, HtmlImageLoadEventArgs e)
{
using (var client = new WebClient())
{
var url = e.Src;
if (!e.Src.StartsWith("http://") && !e.Src.StartsWith("https://"))
{
url = Properties.Settings.Default.BaseUrl.TrimEnd('/') + e.Src;
}
using (var stream = new MemoryStream(client.DownloadData(url)))
{
e.Callback(XImage.FromStream(stream));
}
}
}
Я опаздываю на вашу проблему, но, возможно, это поможет кому-то другому.
Я использовал абсолютные URL-адреса, и они были правильными. Изображения загружались правильно, когда я открывал html-файл в браузере.
Однако они не были загружены после того, как я преобразовал этот html в pdf. Поэтому я попытался использовать обратный вызов разрешения изображения, как предложил @ohjo. Здесь произошло исключение: существующее соединение было принудительно закрыто удаленным хостом.
Я смог решить эту проблему, но добавил еще одну строку, которая устанавливает SecurityProtocol в это решение:
var pdf = PdfGenerator.GeneratePdf(Html, PageSize.A4, 20, null, OnStylesheetLoad, OnImageLoadPdfSharp);
... ...
public static void OnImageLoadPdfSharp(object sender, HtmlImageLoadEventArgs e)
{
var url = e.Src;
if (!e.Src.StartsWith("http://") && !e.Src.StartsWith("https://"))
{
var ImgFilePath = System.Web.HttpContext.Current.Server.MapPath(url);
if (XImage.ExistsFile(ImgFilePath))
e.Callback(XImage.FromFile(ImgFilePath));
var ImgFilePath2 = System.Web.HttpContext.Current.Server.MapPath(url);
if (XImage.ExistsFile(ImgFilePath2))
e.Callback(XImage.FromFile(ImgFilePath2));
}
else
{
using (var client = new WebClient())
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
using (var stream = new MemoryStream(client.DownloadData(url)))
{
e.Callback(XImage.FromStream(stream));
}
}
}
}