在工作流中使用媒体处理程序对资产执行任务

媒体处理程序是与工作流一起使用的服务。

Experience Manager有一些默认的工作流来处理资产。 要查看它们,请打开“工作流”控制台,然后单击​ 模型 ​选项卡:以Assets开头的工作流标题是特定于资产的工作流标题。

可以扩展现有工作流,并创建新工作流以根据特定要求处理资产。

以下示例演示如何增强 AEM Assets 同步工作流,以便为除 PDF 文档外的所有资产生成子资产。

禁用或启用媒体处理程序

可以通过Apache Felix Web管理控制台禁用或启用媒体处理程序。 禁用媒体处理程序后,将不会对资源执行其任务。

启用/禁用媒体处理程序:

  1. 在浏览器中,导航到https://<host>:<port>/system/console/components
  2. 单击媒体处理程序名称旁边的​ 禁用。 例如:com.day.cq.dam.handler.standard.mp3.Mp3Handler
  3. 刷新页面:媒体处理程序旁边会显示一个图标,指示已禁用该页面。
  4. 要启用媒体处理程序,请单击媒体处理程序名称旁边的​ 启用

创建媒体处理程序

要支持新的媒体类型或对资产执行特定任务,需要创建媒体处理程序。 本节介绍如何继续。

重要类和接口

启动实现的最佳方法是继承提供的抽象实现,该实现处理大多数事务并提供合理的默认行为: com.day.cq.dam.core.AbstractAssetHandler类。

此类已提供抽象服务描述符。 因此,如果您从此类继承并使用maven-sling-plugin,请确保将继承标志设置为true

实施以下方法:

  • extractMetadata():提取所有可用的元数据。
  • getThumbnailImage():根据传递的资源创建缩略图图像。
  • getMimeTypes():返回资源MIME类型。

以下是示例模板:

package my.own.stuff; /** * @scr.component inherit="true" * @scr.service */ public class MyMediaHandler extends com.day.cq.dam.core.AbstractAssetHandler { // implement the relevant parts }

接口和类包括:

  • com.day.cq.dam.api.handler.AssetHandler接口:此接口描述添加了对特定MIME类型的支持的服务。 添加MIME类型需要实现此接口。 该界面包含用于导入和导出特定文档、用于创建缩略图和提取元数据的方法。

  • com.day.cq.dam.core.AbstractAssetHandler类:此类用作所有其他资产处理程序实现的基础,并提供常用功能。

  • com.day.cq.dam.core.AbstractSubAssetHandler class:

    • 此类用作所有其他资产处理程序实现的基础,并提供常用功能以及子资产提取的常用功能。
    • 启动实现的最佳方法是继承提供的抽象实现,该实现处理大多数事务并提供合理的默认行为:com.day.cq.dam.core.AbstractAssetHandler类。
    • 此类已提供抽象服务描述符。 因此,如果您从此类继承并使用maven-sling-plugin,请确保将继承标志设置为true。

必须实施以下方法:

  • extractMetadata():此方法提取所有可用的元数据。
  • getThumbnailImage():此方法根据传递的资源创建缩略图图像。
  • getMimeTypes():此方法返回资产MIME类型。

以下是示例模板:

包my.own.stuff; /&amp;ast;&amp;ast; &amp;@scr.component inherit="true" &amp;ast; @scr.service &amp;ast;/ public类MyMediaHandler扩展com.day.cq.dam.core.AbstractAssetHandler

接口和类包括:

  • com.day.cq.dam.api.handler.AssetHandler接口:此接口描述添加了对特定MIME类型的支持的服务。 添加MIME类型需要实现此接口。 该界面包含用于导入和导出特定文档、用于创建缩略图和提取元数据的方法。
  • com.day.cq.dam.core.AbstractAssetHandler类:此类用作所有其他资产处理程序实现的基础,并提供常用功能。
  • com.day.cq.dam.core.AbstractSubAssetHandler类:此类用作所有其他资产处理程序实现的基础,并为子资产提取提供常用功能以及常用功能。

示例:创建特定的文本处理程序

在此部分中,您将创建一个特定的文本处理程序,以生成带有水印的缩略图。

按照以下步骤操作:

请参阅开发工具以使用Maven插件安装和设置Eclipse,并设置Maven项目所需的依赖项。

执行以下过程后,将TXT文件上载到Experience Manager时,将提取文件的元数据并生成两个带水印的缩略图。

  1. 在Eclipse中,创建myBundle Maven项目:

    1. 在菜单栏中,单击​ 文件 > 新建 > 其他

    2. 在对话框中,展开Maven文件夹,选择Maven项目,然后单击​ 下一步

    3. 选中“创建简单项目”框和“使用默认Workspace位置”框,然后单击​ 下一步

    4. 定义Maven项目:

      • 组ID: com.day.cq5.myhandler
      • 工件ID: myBundle。
      • 名称:我的Experience Manager包。
      • 描述:这是我的Experience Manager捆绑包。
    5. 单击​ 完成

  2. 将Java™编译器设置为版本1.5:

    1. 右键单击myBundle项目,选择属性。

    2. 选择Java™编译器并将以下属性设置为1.5:

      • 编译器符合性级别
      • 生成的.class文件兼容性
      • Source兼容性
    3. 单击​ 确定。 在对话框窗口中,单击​

  3. pom.xml文件中的代码替换为以下代码:

    <project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <!-- ====================================================================== -->
     <!-- P A R E N T P R O J E C T D E S C R I P T I O N -->
     <!-- ====================================================================== -->
     <parent>
      <groupId>com.day.cq.dam</groupId>
      <artifactId>dam</artifactId>
      <version>5.2.14</version>
      <relativePath>../parent</relativePath>
     </parent>
     <!-- ====================================================================== -->
     <!-- P R O J E C T D E S C R I P T I O N -->
     <!-- ====================================================================== -->
     <groupId>com.day.cq5.myhandler</groupId>
     <artifactId>myBundle</artifactId>
     <name>My CQ5 bundle</name>
     <version>0.0.1-SNAPSHOT</version>
     <description>This is my CQ5 bundle</description>
     <packaging>bundle</packaging>
     <!-- ====================================================================== -->
     <!-- B U I L D D E F I N I T I O N -->
     <!-- ====================================================================== -->
     <build>
      <plugins>
       <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-scr-plugin</artifactId>
       </plugin>
       <plugin>
        <groupId>org.apache.sling</groupId>
        <artifactId>maven-sling-plugin</artifactId>
        <configuration>
         <slingUrlSuffix>/libs/dam/install/</slingUrlSuffix>
        </configuration>
       </plugin>
       <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
         <instructions>
          <Bundle-Category>cq5</Bundle-Category>
          <Export-Package> com.day.cq5.myhandler </Export-Package>
         </instructions>
        </configuration>
       </plugin>
      </plugins>
     </build>
     <!-- ====================================================================== -->
     <!-- D E P E N D E N C I E S -->
     <!-- ====================================================================== -->
     <dependencies>
      <dependency>
       <groupId>com.day.cq.dam</groupId>
       <artifactId>cq-dam-api</artifactId>
       <version>5.2.10</version>
       <scope>provided</scope>
      </dependency>
      <dependency>
       <groupId>com.day.cq.dam</groupId>
       <artifactId>cq-dam-core</artifactId>
       <version>5.2.10</version>
       <scope>provided</scope>
      </dependency>
      <dependency>
       <groupId>com.day.cq</groupId>
       <artifactId>cq-commons</artifactId>
      </dependency>
      <dependency>
       <groupId>javax.jcr</groupId>
       <artifactId>jcr</artifactId>
      </dependency>
      <dependency>
       <groupId>org.apache.felix</groupId>
       <artifactId>org.osgi.compendium</artifactId>
      </dependency>
      <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
      </dependency>
      <dependency>
       <groupId>commons-lang</groupId>
       <artifactId>commons-lang</artifactId>
      </dependency>
      <dependency>
       <groupId>commons-collections</groupId>
       <artifactId>commons-collections</artifactId>
      </dependency>
      <dependency>
       <groupId>commons-io</groupId>
       <artifactId>commons-io</artifactId>
      </dependency>
      <dependency>
       <groupId>com.day.commons</groupId>
       <artifactId>day-commons-gfx</artifactId>
      </dependency>
      <dependency>
       <groupId>com.day.commons</groupId>
       <artifactId>day-commons-text</artifactId>
      </dependency>
      <dependency>
       <groupId>com.day.cq.workflow</groupId>
       <artifactId>cq-workflow-api</artifactId>
      </dependency>
      <dependency>
       <groupId>com.day.cq.wcm</groupId>
       <artifactId>cq-wcm-foundation</artifactId>
       <version>5.2.22</version>
      </dependency>
     </dependencies>
    
  4. 创建包com.day.cq5.myhandler,其中包含myBundle/src/main/java下的Java™类:

    1. 在myBundle下,右键单击src/main/java,选择新建,然后选择包。
    2. 将其命名为com.day.cq5.myhandler,然后单击“完成”。
  5. 创建Java™类MyHandler

    1. 在Eclipse中的myBundle/src/main/java下,右键单击com.day.cq5.myhandler包。 选择新建,然后选择类。
    2. 在对话框窗口中,将Java™类命名为MyHandler并单击完成。 Eclipse创建并打开文件MyHandler.java
    3. MyHandler.java中,使用以下内容替换现有代码,然后保存更改:
    package com.day.cq5.myhandler;
    import java.awt.Color;
    import java.awt.Rectangle;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import javax.jcr.Node;
    import javax.jcr.RepositoryException;
    import javax.jcr.Session;
    import org.apache.commons.io.IOUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import com.day.cq.dam.api.metadata.ExtractedMetadata;
    import com.day.cq.dam.core.AbstractAssetHandler;
    import com.day.image.Font;
    import com.day.image.Layer;
    import com.day.cq.wcm.foundation.ImageHelper;
    
    /**
     * The <code>MyHandler</code> can extract text files
     * @scr.component inherit="true" immediate="true" metatype="false"
     * @scr.service
     *
     **/
    
    public class MyHandler extends AbstractAssetHandler {
     /** * Logger instance for this class. */
     private static final Logger log = LoggerFactory.getLogger(MyHandler.class);
     /** * Music icon margin */
     private static final int MARGIN = 10;
     /** * @see com.day.cq.dam.api.handler.AssetHandler#getMimeTypes() */
     public String[] getMimeTypes() {
      return new String[] {"text/plain"};
     }
    
     public ExtractedMetadata extractMetadata(Node asset) {
      ExtractedMetadata extractedMetadata = new ExtractedMetadata();
      InputStream data = getInputStream(asset);
      try {
       // read text data
       InputStreamReader reader = new InputStreamReader(data);
       char[] buffer = new char[4096];
       String text = "";
       while (reader.read(buffer) != -1) {
        text += new String(buffer);
       }
       reader.close();
       long wordCount = this.wordCount(text);
       extractedMetadata.setProperty("text", text);
       extractedMetadata.setMetaDataProperty("Word Count",wordCount);
       setMimetype(extractedMetadata, asset);
      } catch (Throwable t) {
       log.error("handling error: " + t.toString(), t);
      } finally {
       IOUtils.closeQuietly(data);
      }
      return extractedMetadata; }
     // ----------------------< helpers >----------------------------------------
     protected BufferedImage getThumbnailImage(Node node) {
      ExtractedMetadata metadata = extractMetadata(node);
      final String text = (String) metadata.getProperty("text");
      // create text layer
      final Layer layer = new Layer(500, 600, Color.WHITE);
      layer.setPaint(Color.black);
      Font font = new Font("Arial", 12);
      String displayText = this.getDisplayText(text, 600, 12);
      if(displayText!=null && displayText.length() > 0) {
       // commons-gfx Font class would throw IllegalArgumentException on empty or null text
       layer.drawText(10, 10, 500, 600, displayText, font, Font.ALIGN_LEFT, 0, 0);
      }
      // create watermark and merge with text layer
      Layer watermarkLayer;
      try {
       final Session session = node.getSession();
       watermarkLayer = ImageHelper.createLayer(session, "/content/dam/we-retail/en/products/apparel/gloves/Gloves.jpg");
       watermarkLayer.setX(MARGIN);
       watermarkLayer.setY(MARGIN);
       layer.merge(watermarkLayer);
      } catch (RepositoryException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      } catch (IOException e) {
       // TODO Auto-generated catch block
       e.printStackTrace(); }
      layer.crop(new Rectangle(510, 600));
      return layer.getImage(); }
     // ---------------< private >-----------------------------------------------
     /**
      * This method cuts lines if the text file is too long..
      * * @param text
      * * text to check
      * * @param height
      * * text box height (px)
      * * @param fontheight
      * * font height (px)
      * * @return the text which will fit into the box
      */
     private String getDisplayText(String text, int height, int fontheight) {
      String trimmedText = text.trim();
      int numOfLines = height / fontheight;
      String lines[] = trimmedText.split("\n");
      if (lines.length <= numOfLines) {
       return trimmedText;
      } else {
       String cuttetText = "";
       for (int i = 0; i < numOfLines; i++) {
        cuttetText += lines[i] + "\n";
       }
       return cuttetText;
      }
     }
     /**
      * * This method counts the number of words in a string
      * * @param text the String whose words would like to be counted
      * * @return the number of words in the string
      * */
     private long wordCount(String text) {
      // We need to keep track of the last character, if we have two whitespaces in a row we do not want to double count.
      // The starting of the document is always a whitespace.
      boolean prevWhiteSpace = true;
      boolean currentWhiteSpace = true;
      char c; long numwords = 0;
      int j = text.length();
      int i = 0;
      while (i < j) {
       c = text.charAt(i++);
       if (c == 0) { break; }
       currentWhiteSpace = Character.isWhitespace(c);
       if (currentWhiteSpace && !prevWhiteSpace) { numwords++; }
       prevWhiteSpace = currentWhiteSpace;
      }
      // If we do not end with a whitespace then we need to add one extra word.
      if (!currentWhiteSpace) { numwords++; }
      return numwords;
     }
    }
    
  6. 编译Java™类并创建捆绑包:

    1. 右键单击myBundle项目,选择​ 运行方式,然后选择​ Maven安装
    2. myBundle/target下创建了包myBundle-0.0.1-SNAPSHOT.jar(包含已编译的类)。
  7. 在CRX资源管理器中,在/apps/myApp下创建一个节点。 名称= install,类型= nt:folder

  8. 复制包myBundle-0.0.1-SNAPSHOT.jar并将其存储在/apps/myApp/install下(例如,使用WebDAV)。 新文本处理程序现在在Experience Manager中处于活动状态。

  9. 在浏览器中,打开Apache Felix Web管理控制台。 选择组件选项卡并禁用默认文本处理程序com.day.cq.dam.core.impl.handler.TextHandler

基于命令行的媒体处理程序

Experience Manager允许您在工作流中运行任何命令行工具来转换资产(如ImageMagick)并将新演绎版添加到该资产。 仅在托管Experience Manager服务器的磁盘上安装命令行工具,并向工作流添加和配置进程步骤。 调用的进程CommandLineProcess也根据特定的MIME类型进行筛选,并根据新演绎版创建多个缩略图。

以下转换可以自动运行并存储在Assets中:

NOTE
在非Windows系统上,FFmpeg工具在为文件名中包含单引号(')的视频资源生成演绎版时返回错误。 如果您的视频文件的名称包含单引号,请先将其删除,然后再上传到Experience Manager。

CommandLineProcess进程按列出的顺序执行以下操作:

  • 根据特定的MIME类型筛选文件(如果指定)。
  • 在托管Experience Manager服务器的磁盘上创建临时目录。
  • 将原始文件流式传输到临时目录。
  • 执行由步骤的参数定义的命令。 正在临时目录中以运行Experience Manager的用户的权限执行该命令。
  • 将结果流式传输回Experience Manager服务器的格式副本文件夹。
  • 删除临时目录。
  • 如果指定,则根据这些演绎版创建缩略图。 缩略图的数量和尺寸由步骤的参数定义。

使用ImageMagick的示例

以下示例说明如何设置命令行流程步骤,以便每次将具有miMIME e类型GIF或TIFF的资源添加到Experience Manager服务器上的/content/dam时,都会创建原始资源的翻转图像。 还创建了另外三个缩略图140x100、48x48和10x250。

为此,请使用ImageMagick。 ImageMagick是一个免费的命令行软件,用于创建、编辑和合成位图图像。

在托管Experience Manager服务器的磁盘上安装ImageMagick:

  1. 安装ImageMagick:请参阅ImageMagick文档

  2. 设置该工具,以便在命令行中运行convert

  3. 要查看工具是否正确安装,请在命令行上运行以下命令convert -h

    它会显示一个帮助屏幕,其中包含转换工具的所有可能选项。

    NOTE
    在某些Windows版本中,转换命令可能无法运行,因为它与Windows安装中的本机转换实用程序冲突。 在这种情况下,请提及用于将图像文件转换为缩略图的ImageMagick软件的完整路径。 例如:"C:\Program Files\ImageMagick-6.8.9-Q16\convert.exe" -define jpeg:size=319x319 ${filename} -thumbnail 319x319 cq5dam.thumbnail.319.319.png
  4. 要查看该工具是否正常运行,请将JPG映像添加到工作目录中,并在命令行上运行命令convert <image-name>.jpg -flip <image-name>-flipped.jpg。 翻转的图像将添加到目录中。 然后,将命令行流程步骤添加到​ DAM更新资产 ​工作流。

  5. 转到​ 工作流 ​控制台。

  6. 在​ 模型 ​选项卡中,编辑​ DAM更新资产 ​模型。

  7. 将​ 启用Web的演绎版 ​步骤的参数更改为: mime:image/gif,mime:image/tiff,tn:140:100,tn:48:48,tn:10:250,cmd:convert ${directory}/${filename} -flip ${directory}/${basename}.flipped.jpg

  8. 保存工作流。

要测试修改后的工作流,请将资产添加到/content/dam

  1. 在文件系统中,获取您选择的TIFF映像。 将其重命名为myImage.tiff并将其复制到/content/dam,例如,通过使用WebDAV。
  2. 转到​ CQ5 DAM ​控制台,例如https://localhost:4502/libs/wcm/core/content/damadmin.html
  3. 打开资产​ myImage.tiff,并验证是否已创建翻转的图像和三个缩略图。
上一页自定义和扩展 Assets
下一页扩展搜索功能

Experience Manager