Преобразование Docx в изображение с использованием Docx4j и PdfBox вызывает OutOfMemoryError

Я конвертирую первую страницу файла docx в изображение за два шага, используя dox4j и pdfbox, но в настоящее время каждый раз получаю OutOfMemoryError.

Я смог определить, что исключение выдается на самом последнем шаге этого процесса, когда вызывается метод convertToImage, однако я уже некоторое время использую второй шаг этого метода для преобразования PDF-файлов без проблем. поэтому я не понимаю, что может быть причиной, если, возможно, dox4j не кодирует pdf, который я еще не тестировал или поврежден.

Я попытался заменить ByteArrayOutputStream на FileOutputStream, и PDF-файл, похоже, отображается правильно, но не больше, чем я ожидал.

Это код, который я использую:

WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(file);
org.docx4j.convert.out.pdf.PdfConversion c = new org.docx4j.convert.out.pdf.viaXSLFO.Conversion(wordMLPackage);

((org.docx4j.convert.out.pdf.viaXSLFO.Conversion)c).setSaveFO(File.createTempFile("fonts", ".fo"));
ByteArrayOutputStream os = new ByteArrayOutputStream();
c.output(os, new PdfSettings());

byte[] bytes = os.toByteArray();
os.close();

ByteArrayInputStream is = new ByteArrayInputStream(bytes);

PDDocument document = PDDocument.load(is);

PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(0);
BufferedImage image = page.convertToImage(BufferedImage.TYPE_INT_RGB, 96);

is.close();
document.close();

Изменить Чтобы дать больше информации об этой ситуации, этот код запускается в веб-приложении Grails. Я пробовал несколько различных вариантов этого кода, в том числе обнуление всего, что больше не нужно, использование FileInputStream и FileOutputStream, чтобы попытаться сохранить больше физической памяти и проверить вывод docx4j и pdfbox, каждый из которых работает правильно.

Я использую docx4j 2.8.1 и pdfbox 0.7.3, я также пробовал pdf-renderer, но все равно получаю ошибку OutOfMemoryError. Я подозреваю, что docx4j использует слишком много памяти, но не выдает ошибку до преобразования pdf в изображение.

Я бы с удовольствием исключил альтернативный способ преобразования файла docx в pdf или непосредственно в изображение в качестве ответа, однако в настоящее время я пытаюсь заменить jodconverter, который было проблематично запускать на сервере.


person Godwin    schedule 12.10.2012    source источник
comment
Похоже, что часть docx4j в порядке, и вам нужно профилировать convertToImage. Насколько велик массив байтов? Сколько страниц в PDF? Сколько оперативной памяти вы даете java? Если у вас есть PDPage, поможет ли он обнулить другие объекты?   -  person JasonPlutext    schedule 12.10.2012
comment
@JasonPlutext: я должен сделать вывод, что это не просто convertToImage, потому что я могу взять обработанный файл PDF из docx4j после сбоя и повторить попытку только с PDF, и он работает нормально.   -  person Godwin    schedule 12.10.2012
comment
Файл Doc, который я использую в качестве основного теста, имеет размер 52 КБ, а создаваемый им PDF-файл — 38,5 КБ. Я установил свою память Java на 3 ГБ, и она все еще не работает.   -  person Godwin    schedule 12.10.2012
comment
Но нет ничего плохого в содержимом вашего массива байтов, не так ли? (т.е. если вы сохраните его на диск, этот PDF-файл в порядке)   -  person JasonPlutext    schedule 13.10.2012
comment
Насколько я могу судить, ничего плохого, он загружается в просмотрщике без ошибок. Однако я начинаю думать, что это как-то связано с тем, что docx4j использует слишком много памяти, преобразование из dox в pdf занимает несколько секунд, и я даже пытался заменить преобразование изображения на Sun pdfview, и он либо работает и отображается неправильно, либо снова заканчивается память.   -  person Godwin    schedule 13.10.2012
comment
Вы можете обнулить wordMLPackage и объект PdfConversion, как было предложено выше.   -  person JasonPlutext    schedule 14.10.2012
comment
Пробовал обнулять почти все, без изменений.   -  person Godwin    schedule 14.10.2012


Ответы (2)


Я являюсь частью команды XDocreport.

Недавно мы разработали небольшое веб-приложение, развернутое на cloudbees (http://xdocreport-converter.opensagres.cloudbees.net/), которое показывает преобразователи поведения.

Вы можете легко сравнить поведение и производительность docx4j и xdocreport для преобразования PDF и Html.

Исходный код можно найти здесь:

https://github.com/pascalleclercq/xdocreport-demo (REST-Service-Converter-WebApplication подпапка). и здесь: https://github.com/pascalleclercq/xdocreport/blob/master/remoting/fr.opensagres.xdocreport.remoting.converter.server/src/main/java/fr/opensagres/xdocreport/remoting/converter/server/ConverterResourceImpl.java

Первые цифры, которые я получаю, это то, что Xdocreport примерно в 10 раз быстрее создает PDF, чем Docx4J.

Обратная связь приветствуется.

person Pascal Leclercq    schedule 21.10.2012
comment
Спасибо @Pascal! Я обнаружил, что XDocReport не преобразовывал файлы docx, содержащие заголовки, нижние колонтитулы, таблицы и почти все остальное, что не было правильным текстом. Я обновился до XDocReport 1.0-SNAPSHOT, и хотя мне не удалось заставить ваш код работать, когда я пересмотрел свой код, я теперь могу без проблем конвертировать большинство файлов DocX в PDF. - person Godwin; 22.10.2012
comment
репозиторий maven для xdocreport 1.0.0-SNAPSHOT по адресу oss.sonatype.org/content/repositories/ снимки, похоже, вызывают некоторые проблемы при сборке (в основном тайм-ауты). Есть ли планы обновить его или перенести в другое репо? - person Godwin; 22.10.2012
comment
Я не знал об этих проблемах с тайм-аутом, и я немного удивлен. Я не знаю лучшего бесплатного онлайн-менеджера репозиториев, поэтому вряд ли он скоро изменится. Я бы порекомендовал вам использовать менеджер репо (например, Nexus) самостоятельно, чтобы вы могли кэшировать снимки других людей. Мы планируем выпустить 1.0.0 через несколько недель, этот выпуск будет доступен в центральном репозитории maven, как и другие. - person Pascal Leclercq; 23.10.2012
comment
Не беспокойтесь, я думаю, что многие наши проблемы возникли из-за вчерашней атаки Anonymous на Amazon, но я буду следить за выпуском. Спасибо еще раз! - person Godwin; 23.10.2012

Наконец-то славный успех! Я заменил docx4j на XDocReport, и документ мгновенно преобразуется в PDF. Однако, похоже, есть некоторые проблемы с некоторыми документами, но я ожидаю, что это связано с ОС, на которой они были созданы, и может быть решено с помощью:

PDFViaITextOptions options = PDFViaITextOptions.create().fontEncoding("windows-1250");

Использование соответствующей ОС, а не просто:

PDFViaITextOptions options = PDFViaITextOptions.create();

По умолчанию используется текущая ОС.

Это код, который я сейчас использую для преобразования из DOCX в PDF:

FileInputStream in = new FileInputStream(file);
XWPFDocument document = new XWPFDocument(in);

PDFViaITextOptions options = PDFViaITextOptions.create();

ByteArrayOutputStream out = new ByteArrayOutputStream();
XWPF2PDFViaITextConverter.getInstance().convert(document, out, options);

byte[] bytes = out.toByteArray();
out.close();

ByteArrayInputStream is = new ByteArrayInputStream(bytes);
PDDocument document = PDDocument.load(is);

PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(0);
BufferedImage image = page.convertToImage(BufferedImage.TYPE_INT_RGB, 96);

is.close();
document.close();

return image;
person Godwin    schedule 15.10.2012
comment
Очень интересно, спасибо. В последнее время у меня было много проблем с преобразованием PDF в docx4j, и это может быть именно то, что требуется. - person Ben; 26.06.2013
comment
(В качестве обновления я вернул свой собственный код к реализации docx4j FOP. XDocReport выглядит многообещающе, но в том, как он форматирует контент, слишком много пробелов (т. е. точность еще недостаточно хороша). YMMV. - person Ben; 19.11.2013