【问题标题】:How to load ICC profile from classpath?如何从类路径加载 ICC 配置文件?
【发布时间】:2017-05-13 09:47:36
【问题描述】:

在尝试使用 Jasper Reports 生成符合 PDF/A 标准的 PDF 时,我得到了

net.sf.jasperreports.engine.util.JRPdfaIccProfileNotFoundException. 

这很容易通过配置解决

<property name="net.sf.jasperreports.export.pdfa.icc.profile.path" value="/stuff/myicc.icc"/>

但我需要将 icc 配置文件与 WAR 的其余部分捆绑在一起,就像报告嵌入的字体一样。如何才能做到这一点?我看起来像

<property name="net.sf.jasperreports.export.pdfa.icc.profile.path" value="classpath:/jasper/someicc.icc"/>

但这不起作用,与报告本身相关的 icc 配置文件也不起作用。我可以将 InputStream 作为参数传递给 PDFGenerator 吗?

【问题讨论】:

    标签: java jasper-reports pdfa color-profile color-management


    【解决方案1】:

    如果您从 java 代码导出,您可以使用 getClassLoader().getResource() 获取文件的绝对路径。

    JRPdfExporter 示例

    JRPdfExporter exporter = new JRPdfExporter();
    //... your input and output
    SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
    URL path = this.getClass().getClassLoader().getResource("jasper/someicc.icc");
    configuration.setIccProfilePath(path.getFile());
    //other settings
    exporter.setConfiguration(configuration);
    exporter.exportReport();
    

    【讨论】:

      【解决方案2】:

      我们最终创建了自己的扩展来处理类路径加载,使其更加集中。

      实现类路径扩展的代码在这里:

      package com.somepackage;
      
      import java.io.InputStream;
      import java.util.Collections;
      import java.util.List;
      
      import net.sf.jasperreports.engine.JRPropertiesMap;
      import net.sf.jasperreports.extensions.ExtensionsRegistry;
      import net.sf.jasperreports.extensions.ExtensionsRegistryFactory;
      import net.sf.jasperreports.repo.InputStreamResource;
      import net.sf.jasperreports.repo.RepositoryService;
      import net.sf.jasperreports.repo.Resource;
      
      /**
       * JasperReports extension factory that enables to read from classpath. Only tries to resolve URLs that start with "classpath:".
       */
      public class ClasspathExtensionsRegistryFactory implements ExtensionsRegistryFactory {
      
          @Override
          public ExtensionsRegistry createRegistry(String registryId, JRPropertiesMap properties) {
              return extFactory;
          }
      
          private static final ClasspathRepositoryService service = new ClasspathRepositoryService();
          private static final List<ClasspathRepositoryService> services = Collections.singletonList(service);
          private static final ExtensionsRegistry extFactory = new ExtensionsRegistry() {
              @SuppressWarnings("unchecked")
              @Override
              public <T> List<T> getExtensions(Class<T> extensionType) {
                              if (RepositoryService.class.equals(extensionType)) {
                                  return (List<T>) services;
                              }
                              return null;
                      }
          };
      
          /**
           * RepositoryService that reads resources from classpath.
           */
          public static class ClasspathRepositoryService implements RepositoryService {
      
              private static final String CLASSPATH_PREFIX = "classpath:";
              private static final int CLASSPATH_PREFIX_LENGTH = CLASSPATH_PREFIX.length();
      
              @Override
              public Resource getResource(String uri) {
                  return getResource(uri, InputStreamResource.class);
              }
      
              @Override
              public void saveResource(String uri, Resource resource) {
                  //No-op
              }
      
              @SuppressWarnings("unchecked")
              @Override
              public <K extends Resource> K getResource(String uri, Class<K> resourceType) {
                  if (resourceType != null && InputStreamResource.class.equals(resourceType) && uri != null && uri.trim().startsWith(CLASSPATH_PREFIX)) {
                      InputStream is = this.getClass().getResourceAsStream(uri.trim().substring(CLASSPATH_PREFIX_LENGTH));
                      if (is != null) {
                          InputStreamResource isr = new InputStreamResource();
                          isr.setInputStream(is);
                          isr.setName(uri);
                          return (K)isr;
                      }
                  }
                  return null;
              }
      
          }
      
      }
      

      之后唯一要做的就是添加 jasperreports_extension.properties 文件,其中包含 net.sf.jasperreports.extension.registry.factory.classpathresourcereader=com.somepackage.ClasspathExtensionsRegistryFactory

      这使人们可以像这样配置导出器:

      SimplePdfExporterConfiguration pec = new SimplePdfExporterConfiguration();
      .
      .
      .
      pec.setIccProfilePath("classpath:/somefolder/iccprofile.icc");
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-17
        • 2014-10-10
        • 1970-01-01
        相关资源
        最近更新 更多