Вопрос или проблема
Я пытаюсь объединить два файла .pdf – один приходит ко мне в виде массива байтов, второй я храню в ресурсе – затем мне нужно вернуть объединенные PDF в виде массива байтов. Я пытаюсь сделать это, используя временные файлы – я предпочитаю избегать создания и удаления папок локально – и используя Apache PdfBox. При выполнении pdfMergerUtility.mergeDocuments() я получил исключение End-of-File.
Мой код выглядит следующим образом:
public byte[] mergedPdfs(byte[] byteArray) throws IOException {
//Сначала я преобразую byteArray в .pdf и пытаюсь сохранить его как временный файл
File pdfOneTemp = File.createTempFile("pdfOne", ".pdf");
FileUtils.writeByteArrayToFile(pdfOneTemp, byteArray);
InputStream pdfOne = new FileInputStream(pdfOneTemp);
//Извлекаем второй .pdf из папки ресурсов (/pdf/pdfTwo.pdf)
InputStream pdfTwo =
Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("/pdf/pdfTwo.pdf");
//ByteArrayOutputStream для потока назначения для PDFMergerUtility
ByteArrayOutputStream mergedPdfs = new ByteArrayOutputStream();
//PDFMergerUtility для объединения двух .pdf файлов
PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
pdfMergerUtility.setDestinationStream(mergedPdfs);
pdfMergerUtility.addSource(pdfOne);
pdfMergerUtility.addSource(pdfTwo);
pdfMergerUtility.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
pdfOne.close();
pdfTwo.close();
return mergedPdfs.toByteArray();
}
И трассировка стека:
SEVERE [org.primefaces.application.exceptionhandler.PrimeExceptionHandler] (default task-2) Error: End-of-File, expected line at offset 0: java.io.IOException: Error: End-of-File, expected line at offset 0
at org.apache.pdfbox.pdfparser.BaseParser.readLine(BaseParser.java:1147)
at org.apache.pdfbox.pdfparser.COSParser.parseHeader(COSParser.java:2651)
at org.apache.pdfbox.pdfparser.COSParser.parsePDFHeader(COSParser.java:2634)
at org.apache.pdfbox.pdfparser.PDFParser.parse(PDFParser.java:217)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1237)
at org.apache.pdfbox.pdmodel.PDDocument.load(PDDocument.java:1155)
at org.apache.pdfbox.multipdf.PDFMergerUtility.legacyMergeDocuments(PDFMergerUtility.java:459)
at org.apache.pdfbox.multipdf.PDFMergerUtility.mergeDocuments(PDFMergerUtility.java:349)
at com.ista.dws.managedBean.searchContract.util.DoSomething.testFiles(DoSomething.java:125)
at com.ista.dws.managedBean.searchContract.SearchContractActionBase.searchContracts(SearchContractActionBase.java:192)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at javax.el.ELUtil.invokeMethod(ELUtil.java:245)
at javax.el.BeanELResolver.invoke(BeanELResolver.java:338)
at javax.el.CompositeELResolver.invoke(CompositeELResolver.java:198)
at com.sun.el.parser.AstValue.invoke(AstValue.java:261)
at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:280)
at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at org.jboss.weld.module.web.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
at org.jboss.weld.module.web.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:65)
at com.sun.faces.application.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:66)
at com.sun.faces.application.ActionListenerImpl.getNavigationOutcome(ActionListenerImpl.java:82)
at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:71)
at javax.faces.component.UICommand.broadcast(UICommand.java:222)
at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:847)
at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1395)
at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:58)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:76)
at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:177)
at javax.faces.webapp.FacesServlet.executeLifecyle(FacesServlet.java:707)
at javax.faces.webapp.FacesServlet.service(FacesServlet.java:451)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:81)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.opentracing.contrib.jaxrs2.server.SpanFinishingFilter.doFilter(SpanFinishingFilter.java:52)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at com.ista.shared.gui.jsf.utils.filter.CharacterEncodingFilter.doFilter(CharacterEncodingFilter.java:21)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.DisableCacheHandler.handleRequest(DisableCacheHandler.java:33)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:53)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:59)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at org.wildfly.extension.undertow.deployment.GlobalRequestControllerHandler.handleRequest(GlobalRequestControllerHandler.java:68)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:376)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
at java.lang.Thread.run(Thread.java:750)
Я пытался сделать все, чтобы это сработало, но, к сожалению, не смог. Что я делаю не так?
Ответ или решение
Ошибка "End-of-File Exception" при слиянии PDF-документов с помощью Apache PdfBox может возникнуть по нескольким причинам. Давайте рассмотрим вашу реализацию и предложим возможные решения.
1. Анализ проблемы
Согласно вашему коду, вы пытаетесь объединить два PDF-файла: один из них представлен в виде массива байтов, а второй загружается из ресурсов вашего приложения. Ошибка "End-of-File, expected line at offset 0" указывает на то, что один из ваших входных PDF-файлов оказывается пустым или поврежденным.
Давайте разберемся в вашем коде:
public byte[] mergedPdfs(byte[] byteArray) throws IOException {
// Создание временного файла для первого PDF
File pdfOneTemp = File.createTempFile("pdfOne", ".pdf");
FileUtils.writeByteArrayToFile(pdfOneTemp, byteArray);
InputStream pdfOne = new FileInputStream(pdfOneTemp);
// Получение второго PDF из ресурсов
InputStream pdfTwo =
Thread.currentThread()
.getContextClassLoader()
.getResourceAsStream("/pdf/pdfTwo.pdf");
// Выводной поток для объединенных PDF
ByteArrayOutputStream mergedPdfs = new ByteArrayOutputStream();
// Объединение документов
PDFMergerUtility pdfMergerUtility = new PDFMergerUtility();
pdfMergerUtility.setDestinationStream(mergedPdfs);
pdfMergerUtility.addSource(pdfOne);
pdfMergerUtility.addSource(pdfTwo);
pdfMergerUtility.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
// Закрытие потоков
pdfOne.close();
pdfTwo.close();
return mergedPdfs.toByteArray();
}
2. Возможные причины ошибки
-
Пустой байтовый массив: Убедитесь, что
byteArray
не является пустым. Вы можете добавить проверку:if (byteArray == null || byteArray.length == 0) { throw new IllegalArgumentException("Input byte array is null or empty"); }
-
PDF файл в ресурсе: Проверьте, действительно ли файл
/pdf/pdfTwo.pdf
существует и корректно загружается. Вы можете добавить проверку на null:if (pdfTwo == null) { throw new IOException("Resource not found: /pdf/pdfTwo.pdf"); }
-
Проблемы с временным файлом: Убедитесь, что временный файл создается и записывается без ошибок. Вы уже используете
FileUtils.writeByteArrayToFile
, но стоит убедиться, что запись действительно успешна.
3. Рекомендации по улучшению
-
Закрытие потоков: Рекомендуется использовать конструкцию try-with-resources для автоматического закрытия потоков:
try (InputStream pdfOne = new FileInputStream(pdfOneTemp); InputStream pdfTwo = Thread.currentThread().getContextClassLoader().getResourceAsStream("/pdf/pdfTwo.pdf"); ByteArrayOutputStream mergedPdfs = new ByteArrayOutputStream()) { // Объединение }
-
Логирование ошибок: Используйте логирование, чтобы отслеживать ошибки и исключения. Это поможет вам быстрее находить проблемные места в коде.
4. Заключение
Проверив вышеуказанные моменты, вы сможете устранить проблему "End-of-File Exception" при объединении ваших PDF-документов. Помните, что важно проверять как входные данные, так и состояние файлов, с которыми вы работаете. Надеемся, данная информация окажется полезной и поможет вам успешно завершить вашу задачу по объединению PDF-файлов. Якщо у вас є додаткові питання або потрібно більше інформації, не соромтеся запитувати.