How to get thumbnails from PDF How to get thumbnails from PDF

Hi there!

Here's a common question about thumbnail preview in Nuxeo from systemz: How to get thumbnails from PDF. This question also applies to other files, like Office or PSD files.

I will mostly need two things for my thumbnail:

  • somewhere to store it
  • a way to generate it.

For the storage part I will use Mixins. In the Nuxeo Platform, this is just a facet that can be added to a document at runtime. I can add it to a document when I know I can generate a thumbnail from the document's BlobHolder.

The definition of the facet is easy:

<extension target="org.nuxeo.ecm.core.schema.TypeService" point="schema">
<schema name="thumbnail" src="schemas/thumbnail.xsd" prefix="thumb" />

<extension target="org.nuxeo.ecm.core.schema.TypeService" point="doctype">
<facet name="Thumbnail">
<schema name="thumbnail" />

Now I have a facet called Thumbnail that adds the thumbnail schema to the document. If you don't know how to add a facet at runtime, it is quite simple:


Then you can simply do:

doc.setPropertyValue("thumbnail:content", (Serializable) myThumbnailBlob);

And to generate my thumbnail, I will use a very simple converter relying on a mighty ImageMagick command. It creates a png thumbnail of any image or file supported by ImageMagick. It can, for instance, take the first page of a PDF or a PSD file.

<extension target="org.nuxeo.ecm.platform.commandline.executor.service.CommandLineExecutorComponent"
<command name="toThumbnail" enabled="true">
<parameterString>-strip -thumbnail 100x100 -background transparent -gravity center -extent 100x100 -format png -quality 75 #{inputFilePath}[0] #{outputFilePath}</parameterString>
<winParameterString>-strip -thumbnail 100x100 -background transparent -gravity center -extent 100x100 -format png -quality 75 #{inputFilePath}[0] #{outputFilePath}</winParameterString>
<installationDirective>You need to install ImageMagick.</installationDirective>

To call that command, let's use a Converter. This is a simple class implementing the Converter interface.

package org.nuxeo.thumb;

import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
import org.nuxeo.ecm.core.api.impl.blob.FileBlob;
import org.nuxeo.ecm.core.convert.api.ConversionException;
import org.nuxeo.ecm.core.convert.cache.SimpleCachableBlobHolder;
import org.nuxeo.ecm.core.convert.extension.Converter;
import org.nuxeo.ecm.core.convert.extension.ConverterDescriptor;
import org.nuxeo.ecm.platform.commandline.executor.api.CmdParameters;
import org.nuxeo.ecm.platform.commandline.executor.api.CommandAvailability;
import org.nuxeo.ecm.platform.commandline.executor.api.CommandLineExecutorService;
import org.nuxeo.ecm.platform.commandline.executor.api.ExecResult;
import org.nuxeo.runtime.api.Framework;


  • @author ldoguin
    public class ThumbnailConverter extends IMImageUtils implements Converter {

    private static final Log log = LogFactory.getLog(ThumbnailConverter.class);

    public BlobHolder convert(BlobHolder blobHolder,

         Map&lt;String, Serializable&gt; parameters) throws ConversionException {
     try {
         // Make sure the toThumbnail command is available
         CommandLineExecutorService cles = Framework
         CommandAvailability commandAvailability = cles
         if (!commandAvailability.isAvailable()) {
             return null;
         // get the input and output of the command
         Blob blob = blobHolder.getBlob();
         File inputFile = null;
         if (blob instanceof FileBlob) {
             inputFile = ((FileBlob) blob).getFile();
         } else if (blob instanceof SQLBlob) {
             StreamSource source = ((SQLBlob) blob).getBinary()
             inputFile = ((FileSource) source).getFile();
         if (inputFile == null) {
             return null;
         CmdParameters params = new CmdParameters();
         File outputFile = File.createTempFile(&quot;nuxeoImageTarget&quot;, &quot;.&quot;
                 + &quot;png&quot;);
         params.addNamedParameter(&quot;inputFilePath&quot;, inputFile);
         params.addNamedParameter(&quot;outputFilePath&quot;, outputFile);
         ExecResult res = cles.execCommand(&quot;toThumbnail&quot;, params);
         if (!res.isSuccessful()) {
             return null;
         Blob targetBlob = new FileBlob(outputFile);
         Framework.trackFile(outputFile, targetBlob);
         return new SimpleCachableBlobHolder(targetBlob);
     } catch (Exception e) {
         throw new ConversionException(&quot;Thumbnail conversion has failed&quot;, e);


    public void init(ConverterDescriptor descriptor) {

As usual, you have to register that class to an extension point.

<extension target="org.nuxeo.ecm.core.convert.service.ConversionServiceImpl"
<converter name="toThumbnail" class="org.nuxeo.thumb.ThumbnailConverter">

Now I can generate and store the thumbnail. However, some questions remain. When will I generate the thumbnail and add it to the document? Where will I display the brand new thumbnail? What if the main Blob of the document changes? I will try to answer these remaining questions next Monday :-) Stay tuned!