Контент на иврите не отображается при конвертации html в PDF с помощью iTextSharp 5.5.8?
Я использую приведенный ниже код для преобразования HTML-файла в PDF с помощью iTextSharp
Document doc = new Document(iTextSharp.text.PageSize.A4, 10, 20, 5, 35);
var writer = PdfWriter.GetInstance(doc, new FileStream(savePath, FileMode.Create));
var xmlWorkerFontProvider = new XMLWorkerFontProvider();
var cssAppliers = new CssAppliersImpl(new MyFontProvider());
CssFilesImpl cssFiles = new CssFilesImpl();
StyleAttrCSSResolver cssResolver = new StyleAttrCSSResolver(cssFiles);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
htmlContext.SetImageProvider(new ITextImageHandler());
IPipeline pipeline = new CssResolverPipeline(cssResolver, new HtmlPipeline(htmlContext, new PdfWriterPipeline(doc, writer)));
XMLWorker worker = new XMLWorker(pipeline, true);
XMLParser xmlParser = new XMLParser(true, worker, Encoding.Unicode);
doc.Open();
doc.NewPage();
xmlParser.Parse(new StringReader(htmlString.ToString()));
doc.Close();
Для английского контента это работает нормально. Но если содержимое написано на иврите, текст не отображается в PDF.
Я проверил другие ответы, связанные с этим на переполнение стека, но они, кажется, используют HtmlParser, который устарел. Так что я не хочу этим пользоваться.
Пожалуйста, дайте мне знать, если что-то еще требуется. Спасибо за ваше время.
Изменить: После прочтения комментариев я попытался также настроить шрифты. Но все равно не повезло. Ниже обновленный код.
Document document = new Document();
PdfWriter writer =
PdfWriter.GetInstance(document, new FileStream(savePath, FileMode.Create));
document.Open();
var cssResolver = new StyleAttrCSSResolver();
XMLWorkerFontProvider fontProvider =
new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.Register(@"E:\fonts\NotoSansHebrew-Regular.ttf");
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
htmlContext.SetImageProvider(new ITextImageHandler());
PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);
XMLWorker worker = new XMLWorker(css, true);
XMLParser p = new XMLParser(worker);
p.Parse(new StringReader(htmlString.ToString()));
document.Close();
1 ответ
Ниже приведена адаптация кода Бруно с некоторыми фактическими HTML. Чтобы запустить его, вам просто нужно скачать шрифт Noto Sans Hebrew и разместить его на рабочем столе. Без каких-либо изменений (за исключением, возможно, путей к файлам) попробуйте запустить этот код, который работает для меня. (Я протестировал это с 5.5.5, поэтому 5.5.8 должен работать абсолютно).
var file = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
var fontFile = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "NotoSansHebrew-Regular.ttf");
var htmlText = @"<div dir=""rtl"" style=""font-family: Noto Sans Hebrew;"">שלום עולם</div>";
using (var FS = new System.IO.FileStream(file, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var document = new Document()) {
using (var writer = PdfWriter.GetInstance(document, FS)) {
document.Open();
var cssResolver = new StyleAttrCSSResolver();
var fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.Register(fontFile);
var cssAppliers = new CssAppliersImpl(fontProvider);
var htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.SetTagFactory(Tags.GetHtmlTagProcessorFactory());
var pdf = new PdfWriterPipeline(document, writer);
var html = new HtmlPipeline(htmlContext, pdf);
var css = new CssResolverPipeline(cssResolver, html);
var worker = new XMLWorker(css, true);
var p = new XMLParser(worker);
using (var ms = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(htmlText))) {
using (var sr = new StreamReader(ms)) {
p.Parse(sr);
}
}
document.Close();
}
}
}
Хитрость в этом заключается в том, чтобы получить точное название шрифта в вашем HTML, как оно есть в файле шрифта. Что иногда сбивает с толку, так это то, что шрифты могут иметь несколько имен внутри. И чем старше шрифт, тем более вероятно, что он будет иметь эти. Если я правильно помню, у iText есть некоторая эвристика для определения имени шрифта, но если вы хотите воспроизвести его безопасно, вы также можете просто использовать псевдоним и называть его как хотите. Например, вы можете изменить HTML-код на:
var htmlText = @"<div dir=""rtl"" style=""font-family: Gerp;"">שלום עולם</div>";
И все будет работать нормально, пока вы будете использовать псевдоним при регистрации:
fontProvider.Register(fontFile, "Gerp");