gpt4 book ai didi

java - Apache POI OPCPackage 无法保存 Jasper 报告生成的 XLSX

转载 作者:行者123 更新时间:2023-12-01 11:53:45 27 4
gpt4 key购买 nike

总体行动计划是使用 JasperReports API 生成 XLSX 文件,然后将其输入 Apache POI 的加密代码。此处找到的示例:http://www.quicklyjava.com/create-password-protected-excel-using-apache-poi/ .

不幸的是,当文件从 Jasper Report 生成时,我无法对其进行加密,但是如果我要在 MS Excel 中创建一个文件并通过代码加载它,那么它就可以很好地加密。因此,Apache POI 库可以很好地处理来自 Excel 的文件。

调试后我相信我能够查明问题所在。

我们使用 OPCPackage 类打开文件(或者在另一种情况下加载输入流),该类有一个方法 getParts() 可以设置所有字段。其中一个特别重要的是 packageProperties。 packageProperties 似乎正在加载特定的包部分 'application/vnd.openxmlformats-package.core-properties+xml'。但是,在 Jasper Report 生成的 XLSX 文件中找不到该部分,因此保持为空。

// Check OPC compliance rule M4.1
if (part.getContentType().equals(ContentTypes.CORE_PROPERTIES_PART)) {
if (!hasCorePropertiesPart) {hasCorePropertiesPart = true;

如果通过,我们将在下面几行分配 this.packageProperties:

// Core properties case-- use first CoreProperties part we come across
// and ignore any subsequent ones
if (unmarshallPart instanceof PackagePropertiesPart && needCorePropertiesPart) {
this.packageProperties = (PackagePropertiesPart) unmarshallPart;

文件打开正常,但是当我尝试保存文件时,saveImpl 方法调用名为 addPackagePart 的方法saveImpl强> 传入“packageProperties”变量。然后该类会抛出异常,因为该字段为空。来自ZipPackage#saveImpl

// If the core properties part does not exist in the part list,
// we save it as well
if (this.getPartsByRelationshipType(PackageRelationshipTypes.CORE_PROPERTIES).size() == 0 && this.getPartsByRelationshipType(PackageRelationshipTypes.CORE_PROPERTIES_ECMA376).size() == 0 ) {
logger.log(POILogger.DEBUG,"Save core properties part");
// Add core properties to part list ...
addPackagePart(this.packageProperties);

这是一个异常(exception):

org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Fail to save: an error occurs while saving the package : part
at org.apache.poi.openxml4j.opc.ZipPackage.saveImpl(ZipPackage.java:503)
at org.apache.poi.openxml4j.opc.OPCPackage.save(OPCPackage.java:1425)
at com.krfs.web.controller.report.BaseReportController.encryptXlsxOutputStream(BaseReportController.java:717)
at com.krfs.web.controller.report.BaseReportController.generateJasperReportOutput(BaseReportController.java:547)
at com.krfs.web.controller.report.BaseReportController.processReportRunningAndGeneration(BaseReportController.java:382)
at com.krfs.web.controller.report.StandardReportController.processReportRunningAndGeneration(StandardReportController.java:25)
at com.krfs.web.controller.report.StandardReportController.run(StandardReportController.java:82)
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:483)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:215)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:961)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:852)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:837)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:177)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.krfs.web.filter.RedirectFilter.doFilter(RedirectFilter.java:62)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.krfs.web.filter.XssFilter.doFilter(XssFilter.java:17)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.authentication.switchuser.SwitchUserFilter.doFilter(SwitchUserFilter.java:181)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at com.krfs.web.filter.CustomLoginFilter.doFilter(CustomLoginFilter.java:156)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at com.krfs.web.filter.CsrfFilter.doFilter(CsrfFilter.java:52)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at fr.xebia.servlet.filter.ExpiresFilter.doFilter(ExpiresFilter.java:1243)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.krfs.web.filter.SecurityHeadersFilter.doFilter(SecurityHeadersFilter.java:22)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.krfs.web.filter.LoggingFilter.doFilter(LoggingFilter.java:44)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.IllegalArgumentException: part
at org.apache.poi.openxml4j.opc.OPCPackage.addPackagePart(OPCPackage.java:873)
at org.apache.poi.openxml4j.opc.ZipPackage.saveImpl(ZipPackage.java:448)
... 104 more

Jasper Reports 代码是导出 XLSX 文件的标准代码。

JRXlsAbstractExporter exporter = new JRXlsxExporter();

JasperPrint jasperPrint = fillJasperPrint(reportMessenger, reportFile, reportParameters);

exporter.setParameter(JRXlsExporterParameter.JASPER_PRINT, jasperPrint);
exporter.setParameter(JRXlsExporterParameter.OUTPUT_STREAM, outputStream);
exporter.setParameter(JRXlsExporterParameter.IS_DETECT_CELL_TYPE, Boolean.TRUE);
exporter.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, Boolean.FALSE);

exporter.exportReport();

这会很好地创建XLSX,但是当我提取内容并查看包时,我看不到属性部分application/vnd.openxmlformats-package.core-properties+xml显然 Apache POI 需要保存文件。

加密代码:

POIFSFileSystem fs = new POIFSFileSystem();
EncryptionInfo info = new EncryptionInfo(fs, EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword(reportPassword);

try (OPCPackage opc = OPCPackage.open(new ByteArrayInputStream(xlsxOutputStream.toByteArray()))) {
OutputStream os = enc.getDataStream(fs);
opc.save(os);
}

fs.writeFilesystem(encryptedOutputStream);

依赖版本:

jasper 报告 - 4.7.1(我也尝试过 6.0.2,结果相同)

Apache poi - 3.11

所以我的问题是,如何让这两个库协调工作,以便我可以加密来自 jasper 报告的文件?有没有办法在导出文件之前注入(inject)输出类型部分 core-properties+xml ?有没有办法绕过 Apache POI 库来跳过查找该部分?

我希望有人看到类似的东西可以帮助我。

干杯,谢谢!

最佳答案

据我所知,Jasper Reports 正在编写稍微不符合规范的文件。暂时还没有超出 Excel 无法使用它们的支持,但仍然不兼容。

Apache POI 可以很好地读取这些文件,如 unit tests like this one 所示。 Apache POI 也可以保存它们,如果通过 XSSFWorkbook 或类似的东西打开并保存,这会触发丢失部分的创建。

不幸的是,对于您的用例,您正在 OPCPacakge 级别工作,并且那里存在 POI 错误。此问题已在 r1662971 中修复,并将在 POI 3.12 beta 2 及更高版本中修复。

现在,您可以通过更改以下行来触发核心属性创建:

OPCPackage opc = OPCPackage.open(inputFilePath, PackageAccess.READ_WRITE);
OutputStream os = enc.getDataStream(fs);
opc.save(os);

改为:

OPCPackage opc = OPCPackage.open(inputFilePath, PackageAccess.READ_WRITE);
OutputStream os = enc.getDataStream(fs);
opc.getProperties();
opc.save(os);

使用 POI 3.12 beta 2 或更高版本后,您将不需要额外调用 getProperties()

此外,您链接到的 github 中的代码中有一些已弃用的调用,您可能需要查看 TestEncryptor.encryptPackageWithoutCoreProperties()了解如何稍微调整它以使其在不使用已弃用的方法的情况下工作。

关于java - Apache POI OPCPackage 无法保存 Jasper 报告生成的 XLSX,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28593223/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com