конвертировать html-файл с арабскими символами в pdf с использованием java [duplicate]

У меня была такая же ошибка, когда я захотел запустить мой проект WinForms (который включает в себя работу с базой данных SQL Server и отлично работающую на моем ПК) на другом ПК. Проблема была в брандмауэре Windows на моем ПК. Я решил это, добавив два правила. Это вся процедура, позволяющая SQL Server через брандмауэр Windows:

  1. Откройте «Выполнить» и введите services.msc
  2. . Найдите службу для SQL Server (имя экземпляра) и SQL Server Browser. По одному за раз щелкните правой кнопкой мыши, выберите «Свойства», скопируйте путь к файлу exe
  3. . Затем откройте firewall.cpl, нажмите «Разрешить приложение» или добавить правило, добавить ранее скопированный путь (есть процедура вам нужно следовать), проверьте Домен и Частный, снимите флажок Public.

Это ссылка YouTube, где вы можете увидеть эту процедуру: Разрешить SQL Server через брандмауэр Windows

1
задан Hakam Fostok 6 February 2017 в 10:40
поделиться

1 ответ

Пожалуйста, посмотрите примеры ParseHtml7 и ParseHtml8 . Они берут HTML-код с арабскими символами, и они создают PDF-файл с тем же арабским текстом:

A PDF table with HTML content [/g7] An HTML table in PDF [/g8]

Прежде чем мы посмотрим на код, позвольте мне объяснить, что не рекомендуется использовать символы, отличные от ASCII, в исходном коде. Например: это не сделано:

 htmlContentAr = “<p><span> رقم التعميم رقم التعميم</p><p>رقم التعميم ….</span></p>”;

Вы никогда не знаете, как будет храниться файл Java, содержащий эти глифы. Если он не сохранен как UTF-8, символы могут выглядеть как нечто совершенно другое. Известно, что системы управления версиями имеют проблемы с символами, отличными от ASCII, и даже компиляторы могут неправильно кодировать кодировку. Если вы действительно хотите сохранить жестко закодированные значения String в своем коде, используйте нотацию UNICODE. Часть проблемы связана с проблемой кодирования, и вы можете узнать об этом подробнее: Невозможно получить чешских символов при создании PDF

Для примеров, показанных на снимках экрана , Я сохранил следующие файлы, используя кодировку UTF-8:

Это то, что вы найдете в файле arabic.html:

<html>
<body style="font-family: Noto Naskh Arabic">
<p>رقم التعميم رقم التعميم</p>
<p>رقم التعميم</p>
</body>
</html>

Это то, что вы найдете в файле arabic2.html:

<html>
<body style="font-family: Noto Naskh Arabic">
<table>
<tr>
<td dir="rtl">رقم التعميم رقم التعميم</td>
<td dir="rtl">رقم التعميم</td>
</tr>
</table>
</body>
</html>

Вторая часть вашей проблемы касается шрифта. Важно, чтобы вы использовали шрифт, который знает, как рисовать арабские глифы. Трудно поверить, что у вас есть arial.ttf прямо в корне вашего диска C:. Это не очень хорошая идея. Я ожидаю, что вы будете использовать C:/windows/fonts/arialuni.ttf, который, безусловно, знает арабские глифы.

Выбор шрифта недостаточен. Ваш HTML должен знать, какое семейство шрифтов использовать. Поскольку большинство примеров в документации используют Arial, я решил использовать шрифт NOTO. Я открыл эти шрифты, прочитав этот вопрос: iText pdf, не отображающий китайских символов при использовании шрифтов NOTO или Source Hans . Мне очень нравятся эти шрифты, потому что они приятные и (почти) каждый язык поддерживается. Например, я использовал NotoNaskhArabic-Regular.ttf, что означает, что мне нужно определить шрифт familie следующим образом:

style="font-family: Noto Naskh Arabic"

Я определил стиль в теге body моего XML, очевидно, что вы можете выбрать, где чтобы определить его: во внешнем файле CSS в разделе стилей <head>, на уровне тега <td>, ... Этот выбор полностью принадлежит вам, но вы должны определить, какой шрифт использовать.

Конечно: когда XML Worker встречает font-family: Noto Naskh Arabic, iText не знает, где найти соответствующий NotoNaskhArabic-Regular.ttf, если мы не зарегистрируем этот шрифт. Мы можем сделать это, создав экземпляр интерфейса FontProvider. Я решил использовать XMLWorkerFontProvider, но вы можете написать свою собственную реализацию FontProvider:

XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");

Есть еще одно препятствие: арабский текст написан справа налево. Я вижу, что вы хотите определить направление прогона на уровне PdfPCell и добавить контент HTML в эту ячейку с помощью ElementList. Вот почему я впервые написал аналогичный пример, названный ParseHtml7 :

public void createPdf(String file) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    // step 3
    document.open();
    // step 4
    // Styles
    CSSResolver cssResolver = new StyleAttrCSSResolver();
    XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
    fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");
    CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
    // HTML
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
    // Pipelines
    ElementList elements = new ElementList();
    ElementHandlerPipeline pdf = new ElementHandlerPipeline(elements, null);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    // XML Worker
    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));

    PdfPTable table = new PdfPTable(1);
    PdfPCell cell = new PdfPCell();
    cell.setRunDirection(PdfWriter.RUN_DIRECTION_RTL);
    for (Element e : elements) {
        cell.addElement(e);
    }
    table.addCell(cell);
    document.add(table);
    // step 5
    document.close();
}

В HTML нет таблицы, но мы создаем собственный PdfPTable, добавляем контент от HTML до PdfPCell с направлением направления LTR, и мы добавим эту ячейку в таблицу, а таблицу в документ.

Возможно, это ваше фактическое требование, но зачем вы это делаете в таком свернутый путь? Если вам нужна таблица, почему бы вам не создать эту таблицу в HTML и определить, что некоторые ячейки RTL такие:

<td dir="rtl">...</td>

Таким образом, вам не нужно создавать ElementList, вы можете просто проанализировать HTML-файл в формате PDF, как это сделано в примере ParseHtml8 :

public void createPdf(String file) throws IOException, DocumentException {
    // step 1
    Document document = new Document();
    // step 2
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
    // step 3
    document.open();
    // step 4
    // Styles
    CSSResolver cssResolver = new StyleAttrCSSResolver();
    XMLWorkerFontProvider fontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS);
    fontProvider.register("resources/fonts/NotoNaskhArabic-Regular.ttf");
    CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
    HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
    htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());

    // Pipelines
    PdfWriterPipeline pdf = new PdfWriterPipeline(document, writer);
    HtmlPipeline html = new HtmlPipeline(htmlContext, pdf);
    CssResolverPipeline css = new CssResolverPipeline(cssResolver, html);

    // XML Worker
    XMLWorker worker = new XMLWorker(css, true);
    XMLParser p = new XMLParser(worker);
    p.parse(new FileInputStream(HTML), Charset.forName("UTF-8"));;
    // step 5
    document.close();
}

В этом примере требуется меньше кода, и если вы хотите изменить макет , достаточно изменить HTML. Вам не нужно менять код Java.

Еще один пример: в ParseHtml9 я создаю таблицу с английским именем в одном столбце («Lawrence of Arabia») и арабский перевод в другом столбце («لورانس العرب»). Поскольку мне нужны разные шрифты для английского и арабского языков, я определяю шрифт на уровне <td>:

<table>
<tr>
<td>Lawrence of Arabia</td>
<td dir="rtl" style="font-family: Noto Naskh Arabic">لورانس العرب</td>
</tr>
</table>

Для первого столбца используется шрифт по умолчанию, и для записи не требуется специальных настроек слева направо. Для второго столбца я определяю арабский шрифт, и я задал направление прогона "rtl".

Результат выглядит следующим образом:

English next to Arabic [/g9]

Это намного проще, чем то, что вы пытаетесь сделать в своем коде.

5
ответ дан Bruno Lowagie 17 August 2018 в 23:09
поделиться
  • 1
    Спасибо Бруно за ваш быстрый ответ и примеры. Что касается Шрифта, я имею в виду только правильное местоположение. – user2579223 18 May 2015 в 04:59
  • 2
    С вашими примерами я могу создать PDF с 2-х столбчатым английским и арабским текстом из Контента HTML. Содержимое HTML основано на вводе HTMLEditor. Это не вход HTML-страницы или что-то еще. Но проблема связана со следующим: 1. Упорядоченный / неупорядоченный список из содержимого HTML. Список элементов не создается для этих элементов, когда мы выполняем анализ. 2. HTML-контент с тегами заголовка (H1, H2, H3, ....) показывает ошибку при разборе. 3. Межстрочный интервал не учитывается при создании PDF. Пожалуйста, помогите мне в этом отношении. – user2579223 18 May 2015 в 05:04
  • 3
    Это слишком много вопросов, чтобы ответить в комментарии, поэтому я не буду помогать вам в этом канале. Кроме того: вы не говорите мне, какую версию iText / XML Worker вы используете. Некоторые из ваших утверждений ложны: межстрочный интервал соблюдается, как доказано в примере в ответ на вопрос . Установите интервал между строками при использовании XMLWorker для разбора HTML в PDF . Что касается заголовков, см. вопрос о чтении PDF на уровнях заголовков Я не отвечаю на вопросы от людей, которые говорят вещи, которые могут быть легко доказаны неправильно. – Bruno Lowagie 18 May 2015 в 07:34
  • 4
    Еще раз спасибо Бруно. Я использую последнюю версию iTextPDF-5.5.6 и XMLWorker-5.5.6. Для межстрочного интервала я добавил кусок с высотой линии после каждого элемента в цикле и достиг расстояния между элементами. Для разбора заголовков, как я уже упоминал, содержимое HTML находится в редакторе HTML и передано в PDF-поколение. Он имеет & lt; h1 & gt; некоторый текст & lt; / h1 & gt; тег в этом HTML-контенте, но он показывает ошибку как «IllegalArgumentException: Element not Allowed & quot; Кроме того, я пытался жестко кодировать один и тот же HTML-контент из примера parseheaders в качестве входных данных, но не содержал контент, созданный в PDF-файле. – user2579223 18 May 2015 в 12:51
  • 5
    Кажется, вы не знакомы с StackOverflow. Код не добавляется в комментариях. Код добавляется путем размещения вопроса. На ваш текущий вопрос был дан ответ очень подробно, и ответ решил проблему, изложенную в вопросе. К сожалению, вы этого не приняли (вы даже не голосовали). Теперь вы нарушаете раздел комментариев, чтобы размещать вопросы, которые не связаны с ответом на вопрос. Почему я должен прилагать усилия, чтобы ответить на эти вопросы, если мой первоначальный ответ (ответ, на который я потратил драгоценное время) не был оценен? – Bruno Lowagie 19 May 2015 в 07:19
Другие вопросы по тегам:

Похожие вопросы: