【问题标题】:Merging of pdf with digital signature with itext 5.4.0 or greatest gives error将带有数字签名的 pdf 与 itext 5.4.0 或最高版本合并会出现错误
【发布时间】:2014-06-21 13:36:06
【问题描述】:

我在尝试将一些用 itext 创建的 pdf 与数字签名合并时遇到了一个大问题。

这是代码:

             ByteArrayOutputStream  bos = new ByteArrayOutputStream();

             Document document = new Document();
             PdfCopy writer = new PdfCopy(document, bos);

             writer.setMergeFields();                

             document.addTitle("");
             document.open();

             PdfReader reader = null;
             for (int i = 0; i < iss.length; i++) {

                 reader = new PdfReader(iss[i]);                     
                 writer.addDocument(reader);
                 reader.close();
             }
             document.close();
             bos.close();

在执行时我收到此错误:

java.lang.IllegalStateException: Already closed
at com.itextpdf.text.io.ArrayRandomAccessSource.get(ArrayRandomAccessSource.java:65)
at com.itextpdf.text.io.IndependentRandomAccessSource.get(IndependentRandomAccessSource.java:78)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.read(RandomAccessFileOrArray.java:226)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:248)
at com.itextpdf.text.pdf.RandomAccessFileOrArray.readFully(RandomAccessFileOrArray.java:242)
at com.itextpdf.text.pdf.PdfReader.getStreamBytesRaw(PdfReader.java:2522)
at com.itextpdf.text.pdf.PdfReader.getStreamBytesRaw(PdfReader.java:2559)
at com.itextpdf.text.pdf.PRStream.toPdf(PRStream.java:230)
at com.itextpdf.text.pdf.PdfIndirectObject.writeTo(PdfIndirectObject.java:158)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.write(PdfWriter.java:420)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:398)
at com.itextpdf.text.pdf.PdfWriter$PdfBody.add(PdfWriter.java:377)
at com.itextpdf.text.pdf.PdfWriter.addToBody(PdfWriter.java:868)
at com.itextpdf.text.pdf.PdfCopyFieldsImp.closeIt(PdfCopyFieldsImp.java:439)
at com.itextpdf.text.pdf.PdfCopyFieldsImp.close(PdfCopyFieldsImp.java:397)
at com.itextpdf.text.pdf.PdfCopyFields.close(PdfCopyFields.java:159)
at it.almavivaitalia.commons.crystal.utils.ReportClientDocumentManager.mergePdfs(ReportClientDocumentManager.java:310)
at it.almavivaitalia.commons.crystal.utils.ReportClientDocumentManager.exportReportSchedulationPDFMerged(ReportClientDocumentManager.java:632)
at it.consip.pat.common.web.controller.AbstractReportCtrl.exportPDFMerged(AbstractReportCtrl.java:388)
at it.consip.pat.common.web.controller.AbstractReportCtrl.exportReportSchedulationPDFMerged(AbstractReportCtrl.java:334)
at it.consip.fgen.web.interrogazioni.controllers.RicEseConsStampeCtrl.stampaAll(RicEseConsStampeCtrl.java:530)
at it.consip.fgen.web.interrogazioni.controllers.RicEseConsStampeCtrl$$FastClassByCGLIB$$d94d9dbb.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:67)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
at it.consip.fgen.web.interrogazioni.controllers.RicEseConsStampeCtrl$$EnhancerByCGLIB$$b8912b3f_2.stampaAll(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:89)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)
at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:206)
at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:324)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:842)
at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
at org.mortbay.thread.BoundedThreadPool$PoolThread.run(BoundedThreadPool.java:450)

如果我评论代码 writer.setMergeFields();一切正常,但字段没有被复制。

如果我使用 itext 5.3.6 版本,一切正常(使用 PdfCopyField)。

为什么?

【问题讨论】:

    标签: java pdf merge itext digital-signature


    【解决方案1】:

    你的推理有两个错误。一个可以修复,一个不是技术错误,而是一个无法修复的推理错误。

    技术错误: 在关闭 document 之前关闭 reader。那还为时过早。 PdfCopyDocument 需要在调用 document.close() 时访问阅读器。您已经在循环中关闭了 reader 实例,请使用 java.lang.IllegalStateException 通知您资源已已关闭

    您的假设存在的问题:数字签名是保证文档完整性的一种方式。当有人签署一份有 5 页的文件时,该人希望确保他签署了这 5 页,而不是更多,而不是更少。您现在要添加页面。那总是会破坏签名!

    如果您想合并经过数字签名的 PDF 文档: - 禁止收集这些文件:如果这样做,签名将消失或损坏。 - 您唯一的选择是将文档合并到一个便携式集合中。在这种情况下,主 PDF 充当一个包或组合来存储单独的 PDF。这样的 PDF 将保持完整(如果不是:签名中断)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-21
      • 1970-01-01
      • 1970-01-01
      • 2012-04-23
      相关资源
      最近更新 更多