ITextSharpを使用して以下のHTMLをPDFに変換したいのですが、どこから始めればよいかわかりません。
<style>
.headline{font-size:200%}
</style>
<p>
This <em>is </em>
<span class="headline" style="text-decoration: underline;">some</span>
<strong>sample<em> text</em></strong>
<span style="color: red;">!!!</span>
</p>
まず、HTMLとPDFは、ほぼ同時期に作成されたものの、関連していません。 HTMLは、段落や表などの高レベルの情報を伝えることを目的としています。それを制御する方法はありますが、これらのより高いレベルの概念を描くのは最終的にブラウザ次第です。 PDFは、ドキュメントおよびドキュメントmustを「見る」ことを目的としていますレンダリングされる場所はどこでも同じです。
HTMLドキュメントには、100%幅の段落があり、モニターの幅に応じて2行または10行かかる場合があり、印刷する場合は7行になることがあり、携帯電話で見ると20行かかります。ただし、PDFファイルは、レンダリングデバイスに依存しないである必要があるため、画面サイズに関係なく常にレンダリングする必要があります。
上記のmustsのため、PDFは「テーブル」や「段落」などの抽象的なものをサポートしていません。 PDFがサポートする3つの基本的なものがあります:テキスト、線/形状、画像。 (注釈や映画のような他のものがありますが、ここではシンプルにしようとしています。)PDFでは、「here's a段落、ブラウザはあなたのことをする!」。代わりに、「このテキストをこの正確なフォントを使用してこの正確なX、Yの位置に描画します。心配する必要はありません。テキストの幅を以前に計算したので、すべてこの行に収まります」また、「ここにテーブルがある」とは言わず、代わりに「このテキストをこの正確な位置に描いてから、以前に計算した他の正確な位置に長方形を描くので、テキストの周りにあるように見える」 「。
第二に、iTextとiTextSharpはHTMLとCSSを解析します。それでおしまい。 ASP.Net、MVC、Razor、Struts、SpringなどはすべてHTMLフレームワークですが、iText/iTextSharpはそれらを100%認識していません。すべてフレームワーク固有の抽象化であるDataGridViews、Repeater、Templates、Viewsなどと同じです。選択したフレームワークからHTMLを取得するのはyourの責任であり、iTextは役に立ちません。 The document has no pages
という例外が発生した場合、または「iTextがHTMLを解析していない」と思われる場合は、 実際にはしないHTMLがある であることがほぼ確実です。あなたがやる。
第三に、長年使用されてきた組み込みクラスはHTMLWorker
ですが、これはXMLWorker
( Java / 。Net )に置き換えられています。 CSSファイルをサポートせず、最も基本的なCSSプロパティと実際には 特定のタグでのブレーク のみをサポートするHTMLWorker
でゼロ作業が行われています。 このファイルにHTML属性またはCSSプロパティと値 が表示されない場合は、おそらくHTMLWorker
でサポートされていません。 XMLWorker
はより複雑になることがありますが、それらの複雑さも make itmoreextensible です。
以下は、作業中のドキュメントに自動的に追加されるiText抽象化にHTMLタグを解析する方法を示すC#コードです。 C#とJavaは非常に似ているため、これを変換するのは比較的簡単です。例1では、組み込みのHTMLWorker
を使用してHTML文字列を解析します。インラインスタイルのみがサポートされているため、class="headline"
は無視されますが、他のすべては実際に機能するはずです。例#2は、XMLWorker
を代わりに使用することを除いて、最初の例と同じです。例3では、簡単なCSSの例も解析しています。
//Create a byte array that will eventually hold our final PDF
Byte[] bytes;
//Boilerplate iTextSharp setup here
//Create a stream that we can write to, in this case a MemoryStream
using (var ms = new MemoryStream()) {
//Create an iTextSharp Document which is an abstraction of a PDF but **NOT** a PDF
using (var doc = new Document()) {
//Create a writer that's bound to our PDF abstraction and our stream
using (var writer = PdfWriter.GetInstance(doc, ms)) {
//Open the document for writing
doc.Open();
//Our sample HTML and CSS
var example_html = @"<p>This <em>is </em><span class=""headline"" style=""text-decoration: underline;"">some</span> <strong>sample <em> text</em></strong><span style=""color: red;"">!!!</span></p>";
var example_css = @".headline{font-size:200%}";
/**************************************************
* Example #1 *
* *
* Use the built-in HTMLWorker to parse the HTML. *
* Only inline CSS is supported. *
* ************************************************/
//Create a new HTMLWorker bound to our document
using (var htmlWorker = new iTextSharp.text.html.simpleparser.HTMLWorker(doc)) {
//HTMLWorker doesn't read a string directly but instead needs a TextReader (which StringReader subclasses)
using (var sr = new StringReader(example_html)) {
//Parse the HTML
htmlWorker.Parse(sr);
}
}
/**************************************************
* Example #2 *
* *
* Use the XMLWorker to parse the HTML. *
* Only inline CSS and absolutely linked *
* CSS is supported *
* ************************************************/
//XMLWorker also reads from a TextReader and not directly from a string
using (var srHtml = new StringReader(example_html)) {
//Parse the HTML
iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, srHtml);
}
/**************************************************
* Example #3 *
* *
* Use the XMLWorker to parse HTML and CSS *
* ************************************************/
//In order to read CSS as a string we need to switch to a different constructor
//that takes Streams instead of TextReaders.
//Below we convert the strings into UTF8 byte array and wrap those in MemoryStreams
using (var msCss = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_css))) {
using (var msHtml = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(example_html))) {
//Parse the HTML
iTextSharp.tool.xml.XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msHtml, msCss);
}
}
doc.Close();
}
}
//After all of the PDF "stuff" above is done and closed but **before** we
//close the MemoryStream, grab all of the active bytes from the stream
bytes = ms.ToArray();
}
//Now we just need to do something with those bytes.
//Here I'm writing them to disk but if you were in ASP.Net you might Response.BinaryWrite() them.
//You could also write the bytes to a database in a varbinary() column (but please don't) or you
//could pass them to another function for further PDF processing.
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
System.IO.File.WriteAllBytes(testFile, bytes);
HTMLからPDFへの要求には朗報があります。 この回答が示した 、W3C標準 css-break- が問題を解決します。 ..これは、テスト後、今年の最終的な勧告に変わる計画を持つ候補勧告です。
print-css.rocks で示されているように、C#用のプラグインを使用したソリューションはそれほど標準的ではありません。
@Chris HaasはitextSharp
を使用してHTML
をPDF
に変換する方法を非常によく説明してくれました。
私の追加:HtmlTextWriter
を使用することで、HTML
テーブル+インラインCSS内にhtmlタグを配置し、XMLWorker
を使用せずにPDFを取得しました。
編集:サンプルコードの追加:
ASPXページ:
<asp:Panel runat="server" ID="PendingOrdersPanel">
<!-- to be shown on PDF-->
<table style="border-spacing: 0;border-collapse: collapse;width:100%;display:none;" >
<tr><td><img src="abc.com/webimages/logo1.png" style="display: none;" width="230" /></td></tr>
<tr style="line-height:10px;height:10px;"><td style="display:none;font-size:9px;color:#10466E;padding:0px;text-align:right;">blablabla.</td></tr>
<tr style="line-height:10px;height:10px;"><td style="display:none;font-size:9px;color:#10466E;padding:0px;text-align:right;">blablabla.</td></tr>
<tr style="line-height:10px;height:10px;"><td style="display:none;font-size:9px;color:#10466E;padding:0px;text-align:right;">blablabla</td></tr>
<tr style="line-height:10px;height:10px;"><td style="display:none;font-size:9px;color:#10466E;padding:0px;text-align:right;">blablabla</td></tr>
<tr style="line-height:10px;height:10px;"><td style="display:none;font-size:11px;color:#10466E;padding:0px;text-align:center;"><i>blablabla</i> Pending orders report<br /></td></tr>
</table>
<asp:GridView runat="server" ID="PendingOrdersGV" RowStyle-Wrap="false" AllowPaging="true" PageSize="10" Width="100%" CssClass="Grid" AlternatingRowStyle-CssClass="alt" AutoGenerateColumns="false"
PagerStyle-CssClass="pgr" HeaderStyle-ForeColor="White" PagerStyle-HorizontalAlign="Center" HeaderStyle-HorizontalAlign="Center" RowStyle-HorizontalAlign="Center" DataKeyNames="Document#"
OnPageIndexChanging="PendingOrdersGV_PageIndexChanging" OnRowDataBound="PendingOrdersGV_RowDataBound" OnRowCommand="PendingOrdersGV_RowCommand">
<EmptyDataTemplate><div style="text-align:center;">no records found</div></EmptyDataTemplate>
<Columns>
<asp:ButtonField CommandName="PendingOrders_Details" DataTextField="Document#" HeaderText="Document #" SortExpression="Document#" ItemStyle-ForeColor="Black" ItemStyle-Font-Underline="true"/>
<asp:BoundField DataField="Order#" HeaderText="order #" SortExpression="Order#"/>
<asp:BoundField DataField="Order Date" HeaderText="Order Date" SortExpression="Order Date" DataFormatString="{0:d}"></asp:BoundField>
<asp:BoundField DataField="Status" HeaderText="Status" SortExpression="Status"></asp:BoundField>
<asp:BoundField DataField="Amount" HeaderText="Amount" SortExpression="Amount" DataFormatString="{0:C2}"></asp:BoundField>
</Columns>
</asp:GridView>
</asp:Panel>
C#コード:
protected void PendingOrdersPDF_Click(object sender, EventArgs e)
{
if (PendingOrdersGV.Rows.Count > 0)
{
//to allow paging=false & change style.
PendingOrdersGV.HeaderStyle.ForeColor = System.Drawing.Color.Black;
PendingOrdersGV.BorderColor = Color.Gray;
PendingOrdersGV.Font.Name = "Tahoma";
PendingOrdersGV.DataSource = clsBP.get_PendingOrders(lbl_BP_Id.Text);
PendingOrdersGV.AllowPaging = false;
PendingOrdersGV.Columns[0].Visible = false; //export won't work if there's a link in the gridview
PendingOrdersGV.DataBind();
//to PDF code --Sam
string attachment = "attachment; filename=report.pdf";
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/pdf";
StringWriter stw = new StringWriter();
HtmlTextWriter htextw = new HtmlTextWriter(stw);
htextw.AddStyleAttribute("font-size", "8pt");
htextw.AddStyleAttribute("color", "Grey");
PendingOrdersPanel.RenderControl(htextw); //Name of the Panel
Document document = new Document();
document = new Document(PageSize.A4, 5, 5, 15, 5);
FontFactory.GetFont("Tahoma", 50, iTextSharp.text.BaseColor.BLUE);
PdfWriter.GetInstance(document, Response.OutputStream);
document.Open();
StringReader str = new StringReader(stw.ToString());
HTMLWorker htmlworker = new HTMLWorker(document);
htmlworker.Parse(str);
document.Close();
Response.Write(document);
}
}
もちろん、csファイルにiTextSharp Refrencesを含めます
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.html.simpleparser;
using iTextSharp.tool.xml;
お役に立てれば!
ありがとうございました
2018年の時点では、iText7(古いiTextSharpライブラリの次の反復)およびそのHTML to PDFパッケージも利用可能です:itext7.pdfhtml
使い方は簡単です:
HtmlConverter.ConvertToPdf(
new FileInfo(@"Path\to\Html\File.html"),
new FileInfo(@"Path\to\Pdf\File.pdf")
);
メソッドにはさらに多くのオーバーロードがあります。
更新:iText *ファミリー製品には デュアルライセンスモデル :オープンソース向け無料、商用利用向け有料。
次のコードを使用してPDFを作成します
protected void CreatePDF(Stream stream)
{
using (var document = new Document(PageSize.A4, 40, 40, 40, 30))
{
var writer = PdfWriter.GetInstance(document, stream);
writer.PageEvent = new ITextEvents();
document.Open();
// instantiate custom tag processor and add to `HtmlPipelineContext`.
var tagProcessorFactory = Tags.GetHtmlTagProcessorFactory();
tagProcessorFactory.AddProcessor(
new TableProcessor(),
new string[] { HTML.Tag.TABLE }
);
//Register Fonts.
XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.Register(HttpContext.Current.Server.MapPath("~/Content/Fonts/GothamRounded-Medium.ttf"), "Gotham Rounded Medium");
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
var htmlPipelineContext = new HtmlPipelineContext(cssAppliers);
htmlPipelineContext.SetTagFactory(tagProcessorFactory);
var pdfWriterPipeline = new PdfWriterPipeline(document, writer);
var htmlPipeline = new HtmlPipeline(htmlPipelineContext, pdfWriterPipeline);
// get an ICssResolver and add the custom CSS
var cssResolver = XMLWorkerHelper.GetInstance().GetDefaultCssResolver(true);
cssResolver.AddCss(CSSSource, "utf-8", true);
var cssResolverPipeline = new CssResolverPipeline(
cssResolver, htmlPipeline
);
var worker = new XMLWorker(cssResolverPipeline, true);
var parser = new XMLParser(worker);
using (var stringReader = new StringReader(HTMLSource))
{
parser.Parse(stringReader);
document.Close();
HttpContext.Current.Response.ContentType = "application /pdf";
if (base.View)
HttpContext.Current.Response.AddHeader("content-disposition", "inline;filename=\"" + OutputFileName + ".pdf\"");
else
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;filename=\"" + OutputFileName + ".pdf\"");
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Current.Response.WriteFile(OutputPath);
HttpContext.Current.Response.End();
}
}
}