تبدیل HTML فارسی به PDF با استفاده از افزونهی XMLWorker کتابخانهی iTextSharp
نویسنده: وحید نصیری
تاریخ: ۱۳۹۲/۰۵/۲۴ ۱۵:۱۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
public class UnicodeFontProvider : FontFactoryImp
{
static UnicodeFontProvider()
{
// روش صحیح تعریف فونت
var systemRoot = Environment.GetEnvironmentVariable("SystemRoot");
FontFactory.Register(Path.Combine(systemRoot, "fonts\\tahoma.ttf"));
// ثبت سایر فونتها در اینجا
//FontFactory.Register(Path.Combine(Environment.CurrentDirectory, "fonts\\irsans.ttf"));
}
public override Font GetFont(string fontname, string encoding, bool embedded, float size, int style, BaseColor color, bool cached)
{
if (string.IsNullOrWhiteSpace(fontname))
return new Font(Font.FontFamily.UNDEFINED, size, style, color);
return FontFactory.GetFont(fontname, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, size, style, color);
}
} public class ImageProvider : AbstractImageProvider
{
public override string GetImageRootPath()
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
return path + "\\"; // مهم است که این مسیر به بک اسلش ختم شود تا درست کار کند
}
} public static class XMLWorkerUtils
{
/// <summary>
/// نحوه تعریف یک فایل سی اس اس خارجی
/// </summary>
public static ICssFile GetCssFile(string filePath)
{
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
return XMLWorkerHelper.GetCSS(stream);
}
}
} /// <summary>
/// معادل پی دی افی المانهای اچ تی ام ال را جمع آوری میکند
/// </summary>
public class ElementsCollector : IElementHandler
{
private readonly Paragraph _paragraph;
public ElementsCollector()
{
_paragraph = new Paragraph
{
Alignment = Element.ALIGN_LEFT // سبب میشود تا در حالت راست به چپ از سمت راست صفحه شروع شود
};
}
/// <summary>
/// این پاراگراف حاوی کلیه المانهای متن است
/// </summary>
public Paragraph Paragraph
{
get { return _paragraph; }
}
/// <summary>
/// بجای اینکه خود کتابخانه اصلی کار افزودن المانها را به صفحات انجام دهد
/// قصد داریم آنها را ابتدا جمع آوری کرده و سپس به صورت راست به چپ به صفحات نهایی اضافه کنیم
/// </summary>
/// <param name="htmlElement"></param>
public void Add(IWritable htmlElement)
{
var writableElement = htmlElement as WritableElement;
if (writableElement == null)
return;
foreach (var element in writableElement.Elements())
{
fixNestedTablesRunDirection(element);
_paragraph.Add(element);
}
}
/// <summary>
/// نیاز است سلولهای جداول تو در توی پی دی اف نیز راست به چپ شوند
/// </summary>
private void fixNestedTablesRunDirection(IElement element)
{
var table = element as PdfPTable;
if (table == null)
return;
table.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
foreach (var row in table.Rows)
{
foreach (var cell in row.GetCells())
{
cell.RunDirection = PdfWriter.RUN_DIRECTION_RTL;
foreach (var item in cell.CompositeElements)
{
fixNestedTablesRunDirection(item);
}
}
}
}
} using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("test.pdf", FileMode.Create));
pdfWriter.RgbTransparencyBlending = true;
pdfDoc.Open();
var html = @"<span style='color:blue; font-family:tahoma;'><b>آزمایش</b></span>
کتابخانه <i>iTextSharp</i> <u>جهت بررسی فارسی نویسی</u>
<table style='color:blue; font-family:tahoma;' border='1'><tr><td>eeمتن</td></tr></table>
<code>This is a code!</code>
<br/>
<img src='av-13489.jpg' />
";
var cssResolver = new StyleAttrCSSResolver();
// cssResolver.AddCss(XMLWorkerUtils.GetCssFile(@"c:\path\pdf.css"));
cssResolver.AddCss(@"code
{
padding: 2px 4px;
color: #d14;
white-space: nowrap;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
}",
"utf-8", true);
// کار جمع آوری المانهای ترجمه شده به المانهای پی دی اف را انجام میدهد
var elementsHandler = new ElementsCollector();
var htmlContext = new HtmlPipelineContext(new CssAppliersImpl(new UnicodeFontProvider()));
htmlContext.SetImageProvider(new ImageProvider());
htmlContext.CharSet(Encoding.UTF8);
htmlContext.SetAcceptUnknown(true).AutoBookmark(true).SetTagFactory(Tags.GetHtmlTagProcessorFactory());
var pipeline = new CssResolverPipeline(cssResolver,
new HtmlPipeline(htmlContext, new ElementHandlerPipeline(elementsHandler, null)));
var worker = new XMLWorker(pipeline, parseHtml: true);
var parser = new XMLParser();
parser.AddListener(worker);
parser.Parse(new StringReader(html));
// با هندلر سفارشی که تهیه کردیم تمام المانهای اچ تی ام ال به المانهای پی دی اف تبدیل شدند
// الان تنها کافی کافی است تا اینها را در یک جدول راست به چپ محصور کنیم تا درست نمایش داده شوند
var mainTable = new PdfPTable(1) { WidthPercentage = 100, RunDirection = PdfWriter.RUN_DIRECTION_RTL };
var cell = new PdfPCell
{
Border = 0,
RunDirection = PdfWriter.RUN_DIRECTION_RTL,
HorizontalAlignment = Element.ALIGN_LEFT
};
cell.AddElement(elementsHandler.Paragraph);
mainTable.AddCell(cell);
pdfDoc.Add(mainTable);
}
Process.Start("test.pdf"); public class CustomLogger : iTextSharp.text.log.ILogger
{
public iTextSharp.text.log.ILogger GetLogger(Type klass)
{
return this;
}
public iTextSharp.text.log.ILogger GetLogger(string name)
{
return this;
}
public bool IsLogging(iTextSharp.text.log.Level level)
{
return true;
}
public void Warn(string message)
{
System.Diagnostics.Trace.TraceWarning(message);
}
public void Trace(string message)
{
System.Diagnostics.Trace.TraceInformation(message);
}
public void Debug(string message)
{
System.Diagnostics.Trace.TraceInformation(message);
}
public void Info(string message)
{
System.Diagnostics.Trace.TraceInformation(message);
}
public void Error(string message)
{
System.Diagnostics.Trace.TraceError(message);
}
public void Error(string message, Exception e)
{
System.Diagnostics.Trace.TraceError(message + System.Environment.NewLine + e);
}
} iTextSharp.text.log.LoggerFactory.GetInstance().SetLogger(new CustomLogger());
var sb = new StringBuilder();
var stringWriter = new StringWriter(sb);
var doc = new HtmlDocument
{
OptionOutputAsXml = true,
OptionCheckSyntax = true,
OptionFixNestedTags = true,
OptionAutoCloseOnEnd = true,
OptionDefaultStreamEncoding = Encoding.UTF8
};
doc.LoadHtml(htmlContent);
doc.Save(stringWriter);
var xhtml = sb.ToString(); public void Add(IWritable htmlElement)
{
var writableElement = htmlElement as WritableElement;
if (writableElement == null)
return;
foreach (var element in writableElement.Elements())
{
var div = element as PdfDiv;
if (div != null)
{
foreach (var divChildElement in div.Content)
{
fixNestedTablesRunDirection(divChildElement);
_paragraph.Add(divChildElement);
}
}
else
{
fixNestedTablesRunDirection(element);
_paragraph.Add(element);
}
}
} PM> Install-Package iTextSharp PM> Install-Package itextsharp.xmlworker
_paragraph = new Paragraph
{
Alignment = Element.ALIGN_LEFT // سبب میشود تا در حالت راست به چپ از سمت راست صفحه شروع شود
}; fixNestedTablesRunDirection(element);
if (table == null)
return; paragraph.Add("Data") public void Add(IWritable htmlElement)
{
var writableElement = htmlElement as WritableElement;
if (writableElement == null)
return;
foreach (var element in writableElement.Elements())
{
if (element is PdfDiv)
{
var div = element as PdfDiv;
foreach (var divChildElement in div.Content)
{
fixNestedTablesRunDirection(divChildElement);
_paragraph.Add(divChildElement);
}
}
else if(element is Paragraph)
{
var paragraph = element as Paragraph;
paragraph.Alignment = Element.ALIGN_LEFT;
_paragraph.Add(element);
}
else
{
fixNestedTablesRunDirection(element);
_paragraph.Add(element);
}
}
} return File(memoryStream.GetBuffer(), "application/pdf", "Test.pdf");
return File(memoryStream.ToArray(), "application/pdf", "Test.pdf");
public void Add(IWritable htmlElement)
{
var writableElement = htmlElement as WritableElement;
if (writableElement == null)
return;
foreach (var element in writableElement.Elements())
{
if (element is NoNewLineParagraph)
{
var noNewLineParagraph = element as NoNewLineParagraph;
foreach (var item in noNewLineParagraph)
{
fixNestedTablesRunDirection(item);
_paragraph.Add(item);
}
}
else if (element is PdfDiv)