您的位置:首页 > 编程语言 > ASP

【译】Asp.net mvc 使用ITextSharp PDF to HTML (解决img标签问题)

2016-05-30 16:46 591 查看
前言:因项目需求,需要将HTML代码转成PDF。大致上已经实现了,可以是发现使用ITextSharp(我现在的版本是5.5.9)的时候,img标签中的src只能跟绝对路径。

在百度上找了一个上午,有一点关联的解决方案都没有。最后去谷歌求助,终于找到了。

这是原文:http://www.am22tech.com/html-to-pdf/(可能需要FQ)

这是我总结后做的一个例子(使用的是第二个解决方法):http://files.cnblogs.com/files/zuochengsi-9/HTML%E8%BD%ACPDF.zip

不懂的也可以参考我的这篇博客:http://www.cnblogs.com/zuochengsi-9/p/5483808.html

------------------------------------------------------------------

正文:

我正在到处寻找完美的例子,可是没有一个能完美的解决我的需求。我的需求非常简单,如下:

创建一个PDF文档从一个HTML页面。这个HTML里的代码包含的了img标签,同时用的相对路径。

我找到了有价值的信息从这几个地方http://kuujinbo.info/iTextSharp/tableWithImageToPdf.aspx

http://hamang.net/2008/08/14/html-to-pdf-in-net/

最终,可以用下面的asp.net代码解决了我的问题。我希望这也能帮助到你!

[b]必要条件:[/b]

Download and copy iTextSharp.dll 我的版本是5.1.1

[b]问题和解决方案:[/b]

这个新的ITextSharp库,对于HTML代码转PDF已经做的很好了。可是有个主要的缺陷,图片的URL映射只能是绝对路径。

不然HTMLworlker类就会抛异常,如果你用的相对路径。

这里有两个解决方法对于这个问题:

1、用IImageProvider 接口取出所有的图片从HTML代码中,然后再"paste"PDF中。

但是HTML代码中对img修饰的style,例如height和width都不会保留下来。

2、解析HTML代码,同时用绝对的URL替换相对的URL在写入PDF文件之前。

这个方法会保存HTML代码中对与<img>设置的height和width。当然这个方法更好。

不过我还是提供两种解决方案让你自己去选择。

[b]基本的准备:[/b]

添加一个新的page在你的代码中

PostToPDF_AM22.aspx

PostToPDF_AM22.aspx.cs

方法1:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

//HTML to PDF 的引用
using iTextSharp.text;
using iTextSharp.text.html;
using iTextSharp.text.pdf;
using iTextSharp.text.xml;
using iTextSharp.text.html.simpleparser;
using System.IO;
using System.util;
using System.Text.RegularExpressions;
//For converting HTML TO PDF- END

public partial class PostToPDF_AM22 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Get the HTML code from your database or whereever you have stored it and store
//it in HTMLCode variable.
string HTMLCode = string.Empty;
ConvertHTMLToPDF(HTMLCode);
}
protected void ConvertHTMLToPDF(string HTMLCode)
{
HttpContext context = HttpContext.Current;

//Render PlaceHolder to temporary stream
System.IO.StringWriter stringWrite = new StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);

StringReader reader = new StringReader(HTMLCode);

//Create PDF document
Document doc = new Document(PageSize.A4);
HTMLWorker parser = new HTMLWorker(doc);
PdfWriter.GetInstance(doc, new FileStream(Server.MapPath("~") + "/App_Data/HTMLToPDF.pdf",

FileMode.Create));
doc.Open();

/********************************************************************************/
var interfaceProps = new Dictionary<string, Object>();
var ih = new ImageHander() { BaseUri = Request.Url.ToString() };

interfaceProps.Add(HTMLWorker.IMG_PROVIDER, ih);

foreach (IElement element in HTMLWorker.ParseToList(
new StringReader(HTMLCode), null))
{
doc.Add(element);
}
doc.Close();
Response.End();

/********************************************************************************/

}

//handle Image relative and absolute URL's
public class ImageHander : IImageProvider
{
public string BaseUri;
public iTextSharp.text.Image GetImage(string src,
IDictionary<string, string> h,
ChainedProperties cprops,
IDocListener doc)
{
string imgPath = string.Empty;

if (src.ToLower().Contains("http://") == false)
{
imgPath = HttpContext.Current.Request.Url.Scheme + "://" +

HttpContext.Current.Request.Url.Authority + src;
}
else
{
imgPath = src;
}

return iTextSharp.text.Image.GetInstance(imgPath);
}
}
}


方法2:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

//For converting HTML TO PDF- START
using iTextSharp.text;
using iTextSharp.text.html;
using iTextSharp.text.pdf;
using iTextSharp.text.xml;
using iTextSharp.text.html.simpleparser;
using System.IO;
using System.util;
using System.Text.RegularExpressions;
//For converting HTML TO PDF- END

public partial class PostToPDF_AM22 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Get the HTML code from your database or whereever you have stored it and store
//it in HTMLCode variable.
string HTMLCode = string.Empty;
ConvertHTMLToPDF(HTMLCode);
}
protected void ConvertHTMLToPDF(string HTMLCode)
{
HttpContext context = HttpContext.Current;

//Render PlaceHolder to temporary stream
System.IO.StringWriter stringWrite = new StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);

/********************************************************************************/
//Try adding source strings for each image in content
string tempPostContent = getImage(HTMLCode);
/*********************************************************************************/

StringReader reader = new StringReader(tempPostContent);

//Create PDF document
Document doc = new Document(PageSize.A4);
HTMLWorker parser = new HTMLWorker(doc);
PdfWriter.GetInstance(doc, new FileStream(Server.MapPath("~") + "/App_Data/HTMLToPDF.pdf",

FileMode.Create));
doc.Open();

try
{
//Parse Html and dump the result in PDF file
parser.Parse(reader);
}
catch (Exception ex)
{
//Display parser errors in PDF.
Paragraph paragraph = new Paragraph("Error!" + ex.Message);
Chunk text = paragraph.Chunks[0] as Chunk;
if (text != null)
{
text.Font.Color = BaseColor.RED;
}
doc.Add(paragraph);
}
finally
{
doc.Close();
}
}

public string getImage(string input)
{
if (input == null)
return string.Empty;
string tempInput = input;
string pattern = @"<img(.|\n)+?>";
string src = string.Empty;
HttpContext context = HttpContext.Current;

//Change the relative URL's to absolute URL's for an image, if any in the HTML code.
foreach (Match m in Regex.Matches(input, pattern, RegexOptions.IgnoreCase | RegexOptions.Multiline |

RegexOptions.RightToLeft))
{
if (m.Success)
{
string tempM = m.Value;
string pattern1 = "src=[\'|\"](.+?)[\'|\"]";
Regex reImg = new Regex(pattern1, RegexOptions.IgnoreCase | RegexOptions.Multiline);
Match mImg = reImg.Match(m.Value);

if (mImg.Success)
{
src = mImg.Value.ToLower().Replace("src=", "").Replace("\"", "");

if (src.ToLower().Contains("http://") == false)
{
//Insert new URL in img tag
src = "src=\"" + context.Request.Url.Scheme + "://" +
context.Request.Url.Authority + src + "\"";
try
{
tempM = tempM.Remove(mImg.Index, mImg.Length);
tempM = tempM.Insert(mImg.Index, src);

//insert new url img tag in whole html code
tempInput = tempInput.Remove(m.Index, m.Length);
tempInput = tempInput.Insert(m.Index, tempM);
}
catch (Exception e)
{

}
}
}
}
}
return tempInput;
}

string getSrc(string input)
{
string pattern = "src=[\'|\"](.+?)[\'|\"]";
System.Text.RegularExpressions.Regex reImg = new System.Text.RegularExpressions.Regex(pattern,
System.Text.RegularExpressions.RegexOptions.IgnoreCase |

System.Text.RegularExpressions.RegexOptions.Multiline);
System.Text.RegularExpressions.Match mImg = reImg.Match(input);
if (mImg.Success)
{
return mImg.Value.Replace("src=", "").Replace("\"", ""); ;
}

return string.Empty;
}
}


说明:

上面的两种方案,都有一个方法ConvertHTMLToPDF,对于得到的HTML代码的格式是有要求的,具体可以去ITextSharp官网看看。

最后结果存储的一个PDF文档的名字叫HTMLToPDF.pdf在你的web站点的App_Data文件夹里

记得,你需要写代码去拿到HTML代码从你的数据库中或者其他文件里在上面的Page_Load事件中。

通过HTML代码转换函数,它将为您创建PDF文件。

如果你面临任何问题,写在评论中,我会尽力帮助你 。

——————————————————————————————————————

初次翻译,就直接原样翻译了。但通过这次就感觉看英文资料没有以前那种抗拒感了。果然还是有尝试,就会有收获!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: