Grasping Thumbnails in Alfresco 3

With Alfresco 3 (both Labs and Enterprise), Alfresco added a new thumbnail service. It isn’t documented too well yet so I thought I’d write up a quick example.

What is it

The Thumbnail Service is used to create alternate renditions of objects. Typically, those alternate renditions are small images called “thumbnails”. You can see a working application of the thumbnail service if you take a look at Alfresco Share’s document library. When you upload a document, the thumbnail service is invoked, and a small image is shown next to each item in the list.

Where thumbnails live

Like everything else in Alfresco, thumbnails are stored as nodes. Nodes are instances of cm:thumbnail and are stored as children of the object they represent. (You can see this for yourself by looking at the thumbnailed object in the node browser). Objects can have any number of thumbnails. This lets you have thumbnails of different sizes and mime types, for example.

Once Alfresco generates a thumbnail for an object, the object will have the cm:thumbnailed aspect applied to it so it is easy to find or filter objects based on whether or not they have at least one thumbnail.

Thumbnail definitions & thumbnail names

Every thumbnail has a thumbnail definition. The thumbnail definition keeps track of things like the mime type, transformation options, placeholder path, and thumbnail name. The thumbnail name uniquely identifies the thumbnail definition in the thumbnail registry. When you want to generate or display a thumbnail for an object, you must specify the name. For example, given a thumbnail definition named “scImageThumbnail”, you could use JavaScript to create a thumbnail for an object by calling the “createThumbnail” method on a ScriptNode like this:

document.createThumbnail("scImageThumbnail", true);

The first argument is the name of the thumbnail definition. The second argument says the thumbnail should be generated asynchronously.

Registering thumbnail definitions

The thumbnail registry needs to know about your thumbnail definitions. The out-of-the-box thumbnails are registered in the thumbnail-service-context.xml file. I don’t see a clean way to extend that without repeating the definitions, so in my example, I wrote a bean that calls the Thumbnail Registry and registers the custom thumbnail definitions provided in the Spring context file:


public class ThumbnailRegistryBootstrap {
  private ThumbnailService thumbnailService;
  private List<ThumbnailDefinition> thumbnailDefinitions;
  private Logger logger = Logger.getLogger(ThumbnailRegistryBootstrap.class);

public void init() {
  ThumbnailRegistry thumbnailRegistry = thumbnailService.getThumbnailRegistry();
    for (ThumbnailDefinition thumbDef : thumbnailDefinitions) {
      logger.info("Adding thumbnail definition:" + thumbDef.getName());
      thumbnailRegistry.addThumbnailDefinition(thumbDef);
    }
}

public void setThumbnailService(ThumbnailService thumbnailService) {
  this.thumbnailService = thumbnailService;
}

public void setThumbnailDefinitions(
  List<ThumbnailDefinition> thumbnailDefinitions) {
  this.thumbnailDefinitions = thumbnailDefinitions;
}

}

So this class will add all of my thumbnail definitions to the thumbnail registry. The class and the definitions are configured in a Spring context file. The config for a single thumbnail called “scImageThumbnail” which is a PNG 100 pixels high and retains the original aspect ratio of the image would be:


<bean id="someco.thumbnailRegistry"
 class="com.someco.thumbnails.ThumbnailRegistryBootstrap"
 depends-on="ThumbnailService"
 init-method="init">
  <property name="thumbnailService" ref="ThumbnailService" />
  <property name="thumbnailDefinitions">
    <list>
      <bean class="org.alfresco.repo.thumbnail.ThumbnailDefinition">
        <property name="name" value="scImageThumbnail" />
        <property name="mimetype" value="image/png"/>
        <property name="transformationOptions">
          <bean  class="org.alfresco.repo.content.transform.magick.ImageTransformationOptions">
            <property name="resizeOptions">
              <bean class="org.alfresco.repo.content.transform.magick.ImageResizeOptions">
              <property name="height" value="100"/>
              <property name="maintainAspectRatio" value="true"/>
              <property name="resizeToThumbnail" value="true" />
            </bean>
          </property>
        </bean>
     </property>
     <property name="placeHolderResourcePath" value="alfresco/extension/thumbnail/thumbnail_placeholder_scImageThumbnail.png" />
   </bean>
 </list>
 </property>
</bean>

The placeholder is a graphic that the thumbnail service can return as the thumbnail if the thumbnail for a given node has not been generated. In my example I just copied one of the out-of-the-box placeholders and renamed it but you could use anything you want there.

Example

I built a simple example to show how this works. Here is a screencast that shows it running or you can download the source and build it yourself.

In the example, a simple form is presented to allow a file to be uploaded. The form posts to a web script which creates a new node using the file provided. The form GET and POST web scripts are essentially the “helloworldform” web scripts from the Alfresco Developer Guide.

The “image list” is a simple GET web script that queries the folder where the images are uploaded to and writes out a list of image tags. The interesting thing to note here is the URL that’s used:

${url.serviceContext}/api/node/workspace/SpacesStore/${image.id}/content/thumbnails/scImageThumbnail?ph=true&c=queue

That URL is an out-of-the-box web script that returns the specified thumbnail for a given node reference. In my example I’m using the “ph” and “c” arguments. The “ph” argument says whether or not the placeholder image should be returned if the thumbnail does not exist. The “c” argument says that if a thumbnail doesn’t exist, queue a request for thumbnail creation. (Note that the descriptor says the queue create argument is “qc” but if you look at the controller source you’ll see it is actually just “c”. I’ll check to see if there’s a Jira on that).

When you add a new image and then go to the image list you’ll see the placeholder graphic. Behind the scenes, a thumbnail creation request has been queued. If you refresh the page, the thumbnail should show up because Alfresco has had a chance to generate it. If you wanted to queue the request when the node is created, you could either create a rule on the folder that holds the images, or you could add a call to “createThumbnail” in the upload POST web script controller, as shown earlier. (I’ve got an example of that commented out in the source).

That’s it

Hopefully this has given you some insight into the new thumbnail service in Alfresco. If you want to play with it yourself, you can download the source for the example and build it with Ant (make sure you set build.properties to match your environment first) by running “ant deploy”. Make sure you’ve got ImageMagick installed on your Alfresco server–the thumbnail service depends on it. You’ll also need the SDK to compile the registry bootstrap class. If you want to see what the thumbnail service is actually doing you’ll need the Alfresco source. None of the thumbnail source is included in the source code that currently accompanies the SDK.

35 comments

  1. jpbarba says:

    Hi,
    thank you for sharing your knowledge.
    I want to implement thumbnails in Alfresco Explorer,
    and when a new document is added automatically the thumbnail is created. The problem is that there isn’t an action to perform it. I have seen that the thumbnail context file has an entry for the executer but is not public (public = false). I have turned on but it doesn’t work. I would like to implement a thumbnail functionality dor Office and PDF documents. How could I resolve this problem?

    Greetings.

  2. jpotts says:

    Try creating a JavaScript file in Data Dictionary/Scripts that contains a JS call to request thumbnail creation, like this:

    document.createThumbnail(“scImageThumbnail”, true);

    Then set up a rule on the folder that uses the “Execute Script” action and point to the JavaScript file you created in the previous step.

    Jeff

  3. jpbarba says:

    Thank you Jeff,
    I have created an script with this content and i have create a rule to call it when a new PDF is uploaded, but I get this error:

    A system error happened during the operation: Failed to execute script ‘workspace://SpacesStore/b3f91ddc-6e5d-4ec0-ac98-96a1bbb498d4’: The thumbnail name ‘scImageThumbnail’ is not registered

    Jp

  4. david says:

    Hi Jeff,

    How can I add additional mimetypes? For example, I think ImageMagick supports PSD thumbnail creation, but where do I set this up in Alfresco?

    Should I create a definition for the PSD mimetype in the context file? And then try the JS action trick you described to jpbarba?

    Thanks for your help…

  5. jpotts says:

    If you’re working with a file that does not already have a mimetype defined for it in Alfresco, you can extend the out-of-the-box mimetype map.

    First, you need to register your new mimetype map with a bean like so:

    <bean id=”mimetypeConfigService” class=”org.alfresco.config.xml.
    XMLConfigService” init-method=”init”>
    <constructor-arg>
    <bean class=”org.alfresco.config.source.UrlConfigSource”>
    <constructor-arg>
    <list>
    <value>classpath:alfresco/mimetype/mimetype-
    map.xml</value>
    <value>classpath:alfresco/mimetype/mimetype-
    map-openoffice.xml</value>
    <value>classpath:alfresco/extension/someco-
    mimetype-map.xml</value>
    </list>
    </constructor-arg>
    </bean>
    </constructor-arg>
    </bean>

    Then, you can create your custom mimetype map in a file whose name matches the one you specified in the Spring config above, like this:

    <alfresco-config area=”mimetype-map”>
    <config evaluator=”string-compare” condition=”Mimetype Map”>
    <mimetypes>
    <mimetype mimetype=”application/vnd.ms-project”
    display=”Microsoft Project”>
    <extension>mpp</extension>
    </mimetype>
    </mimetypes>
    </config>
    </alfresco-config>

    Now, just because you do that it doesn’t mean that Alfresco’s transformer will be able to create a thumbnail out of it.

    Jeff

  6. david says:

    Hi Jeff,

    Thanks so much for your helpful reply!

    I managed to get both photoshop PSD and illustrator EPS previews working with a combination of the above…
    – added mimetype definitions for application/photoshop and application/postscript
    – added custom transformers (using ImageMagick convert tool) for PSD and EPS
    – created JS that calls document thumbnail function.

    I still have one problem though: my script seems only to be able to create one thumbnail (doclib); and as a result I can only get the really tiny thumbnails at this time. The search goes on…

  7. jpotts says:

    David,

    No problem. When you say your script can only create one thumbnail, I’m not sure I follow. Are you saying you created more than one thumbnail definition in the thumbnail registry but something fails when you call each of them by name?

    Or do you mean that you can call them but the image transformation fails?

    Or something else?

    Jeff

  8. david says:

    Well, I haven’t created any custom thumbnail definitions, as I was trying to use the standard “doclib”, “imgpreview” and “webpreview” thumbnails in thumbnail-service-context.xml, because I want them to show up in the Share document library component, and I figured those are the thumbnails displayed in that.

    When I call document.createThumbnail(“doclib”), it works fine. If I try the other types, though, I get an error “a duplicate image with the same name exists” (or similar, haven’t got the exact message in front of me now).

    I hope that makes sense…

  9. jpotts says:

    David,

    Thumbnails are stored as children of the node they represent and are named using the registered thumbnail name. It seems like the API would keep this from happening but if you created a thumbnail for a node that already had a thumbnail, using the same registered name, I guess that could create a “duplicate child of the same name” kind of situation.

    Not sure if that’s your problem but hopefully it will help.

    Jeff

  10. Kamlesh says:

    Hi Jeff,

    Thanks for the example and the recorded demo of the same.

    I am using Alfresco Labs 3c. I have deployed the thumbnail example to my Alfresco installation. But when I try to upload a file I get the exception:

    org.mozilla.javascript.EcmaError – TypeError: Cannot call method “createFile” of undefined (AlfrescoScript#11)

    The same exception I am getting with Alfresco Enterprise 3.0.1.

    What could be the reason?

    Kamlesh

  11. jpotts says:

    Kamlesh,

    I’d have to see your code to be much help but the error sounds as if you are calling a method on an object that is undefined or null. (Also, I don’t recognize the “createFile” method).

    If you are trying to use “document.createThumbnail” then make sure your “document” variable is actually set to something. That variable gets set automatically if you execute server-side JavaScript against a piece of content through the web client UI via the “execute script” action. Otherwise, you’ll have to do a search or something else to populate it.

    Hope that helps,

    Jeff

  12. Kamlesh says:

    Thanks Jeff,

    You got it right. I have just changed the lucene query and got my thumbnails 🙂

    – Kamlesh

  13. Kamlesh says:

    Hi Jeff,

    Though I can generate thumbnails for image files, I am unable to do the same for PDF and other content types. I have ImageMagick and OpenOffice installed.

    In order to configure PDF, I have added one more bean declaration in someco-thumbnail-context.xml file where I am specifying the contentType as application/pdf for scPdfThumbnail.

    I have modified the javascript to generate scPdfThumbnail like:

    for each (field in formdata.fields) {
    if (field.name == “file” && field.isFile) {
    filename = field.filename;
    content = field.content;
    mimetype = field.mimetype;
    }
    }

    var newDoc = companyhome.createFile(filename);
    newDoc.properties.content.write(content);
    newDoc.properties.content.mimetype = mimetype;
    newDoc.save();

    newDoc.createThumbnail(“scPdfThumbnail”, true);

    When I run this webscript and upload a pdf file, the script runs successfully and the file is uploaded. But no child thumbnail node is created corresponding to the pdf node.

    I am unable to figure out the reason for this. Can you please help me out?

    Also, what are the supported content types for which thumbnails can be generated?

    Regards,
    Kamlesh

  14. jpotts says:

    I haven’t tried PDF. My first thought was to verify that ImageMagick can convert PDF to a graphic format. It turns out it can.

    So my next thought is maybe the thumbnail classes assume “graphic in, graphic out” and aren’t passing ImageMagick the options necessary to handle PDF. You’ll need to step through that code with a debugger to find out.

    Another idea is to look at Share. I know it uses pdf2swf to convert PDF into a pageable SWF file which opens up when you “preview” a document. But it also generates a thumbnail. I grep’d the OOTB context files for a pdf thumbnail config and didn’t find one. So digging into Share to see if it is creating thumbnails of PDFs the same way you want to do it is another route to take.

    Jeff

  15. Kamlesh says:

    Hi Jeff,

    I have also thought in the same direction and checked whether share is generating thumbnails for PDF files or not. So in my local installation of Alfresco share when I upload a PDF file, it is not showing the thumbnail of the PDF and neither for the microsoft word documents. However thumbnails are generated for images as expected and text files in addition. I am debugging more into Alfresco Share to get some pointer.

    – Kamlesh

  16. Kamlesh says:

    Hi Jeff,

    I apologize for the above mentioned statement. Alfresco share do generate thumbnails for PDF files, there might be some issue with my local installation.

    Also, in the example I was trying I noticed that whenever I tried to upload a PDF file the content type of the file was application/binary in place of application/pdf. So I have changed the helloworldform.post.js script to get an existing file from Alfresco’s space. I have called createThumbnail method on this file and saved the file. I have used scImageThumbnail bean as an argument to the createThumbnail method rather than scPdfThumbnail. This has worked and I am able to generate the thumbnail of a PDF file as well as a MS-Word and MS power point files.

    – Kamlesh

  17. Yugoo says:

    for those who looking for a way to generate PSD thumbnail :
    1) write a custom mimetype-map (see above)
    2) a custom mimetype application/photoshop (see above or google it)
    3) a custom content-transformer using the imagemagick “convert” binary.
    a working example : http://pastie.org/820985.txt
    i’m using imagemagick 6.5.8.3

  18. Cláudio says:

    Hi.. I’m using the Alfresco 3.2r2 and I’m having problems to criate thumbnails to each document.

    Is it needed to have ImageMagik installed?

    I tried upload.createThumbnail(doclib,true)…

  19. jpotts says:

    Yes. Install ImageMagick and then make sure your alfresco-global.properties file is pointing to the location of the ImageMagick binary.

    Jeff

  20. Cláudio says:

    I just installed ImageMagick…

    I’m using Fedora and I pointed the alfresco-global.properties to

    ImageMagik dont as a binary…

    it has
    /usr/bin/display
    /usr/bin/convert
    /usr/bin/montage

    i used

    img.root=/usr/bin/convert

    but still nothing…
    Is it right?

  21. jpotts says:

    convert is the name of the ImageMagick binary itself. Alfresco wants the path to the binary, not the binary file (Alfresco already knows the binary is “convert”). So try it without “/convert” and see what happens. If you look at catalina.out you can see where Alfresco will attempt to do a test conversion on startup. It outputs any error messages that happen during the conversion. Use that to help you debug.

    Jeff

  22. Franki says:

    Hello,

    Is it possible to use thumbnails with public alfresco repository?

    If I go to “http://cmis.alfresco.com/s/api/node/workspace/SpacesStore/f9bb33bb-652e-432f-bb61-8fbd495cfb06/content/thumbnails/doclib?qc=queue&ph=true” the place holder is created but no thmubnail is created.

    Thanks in advance,
    Franki

  23. jpotts says:

    Try this instead:

    http://cmis.alfresco.com/s/api/node/workspace/SpacesStore/f9bb33bb-652e-432f-bb61-8fbd495cfb06/content/thumbnails/doclib?c=queue&ph=true

    That will pull up the placeholder graphic, but no thumb gets generated for that file. Looks like your asset is a graphic, so I’m not sure whether the issue is that they don’t have ImageMagick installed/configured properly or there was some problem creating the rendition for your particular file, or some other issue.

    Jeff

  24. Langdon says:

    In the current implementation of the thumbnail service, you kind of get 2 options: 1) generated thumbnail; 2) generating thumbnail placeholder (although, strictly speaking, this placeholder is “no thumbnail available”). Do you know of any way to get a third option which would either be a proper “generating thumbnail placeholder” or a new one “no thumbnail can be created for this mime-type placeholder?” Alternately, a way through the service to know if a thumbnail will eventually be created when using “c=queue” vs just that it isn’t available yet?

  25. jpotts says:

    Unfortunately, no. That may be possible through a customization, but I haven’t looked at it. I definitely get why you are asking. I currently have a client that would benefit from this distinction as well.

  26. Umut Utkan says:

    Answer to

    > The out-of-the-box thumbnails are registered in the thumbnail-service-context.xml file. I don’t see a clean way to extend that without repeating the definitions, so in my example, I wrote a bean that calls the Thumbnail Registry and registers the custom thumbnail definitions provided in the Spring context file:

    Instead of creating a custom bean to register your custom thumbnail definitions, you could have just used MethodInvokingFactory bean to register them directly to the default thumbnailRegistry bean. It is for calling methods on other beans. See the following spring configuration.

    It should work, I used this approach in a lot of places while extending Alfresco since spring configurations are not authored extensibility in mind.

  27. Umut Utkan says:

    I guess xml content in the comments are sanitized. Trying one last time with HTML encoded version of the same config. Sorry about that.

    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" ref="thumbnailRegistry"/>
    <property name="targetMethod" value="addThumbnailDefinition"/>
    <property name="arguments">
    <list>
    <bean class="org.alfresco.repo.thumbnail.ThumbnailDefinition">
    <property name="name" value="scImageThumbnail"/>
    <property name="mimetype" value="image/png"/>
    <property name="transformationOptions">
    <bean class="org.alfresco.repo.content.transform.magick.ImageTransformationOptions">
    <property name="resizeOptions">
    <bean class="org.alfresco.repo.content.transform.magick.ImageResizeOptions">
    <property name="height" value="100"/>
    <property name="maintainAspectRatio" value="true"/>
    <property name="resizeToThumbnail" value="true"/>
    </bean>
    </property>
    </bean>
    </property>
    <property name="placeHolderResourcePath"
    value="alfresco/extension/thumbnail/thumbnail_placeholder_scImageThumbnail.png"/>
    </bean>
    </list>
    </property>
    </bean>

  28. jpotts says:

    Ivan,

    You could have different thumbnail definitions and then ask for the one that has the right height and width, but I know what you really want is to be able to specify and arbitrary height and width at thumbnail request time. There’s not a way to do that out-of-the-box that I know of.

    Jeff

  29. Peter says:

    Hi Jeff,

    What tool is used to generate thumbs? Is that ImageMagick? We are loosing text on the thumbnails and my guess is that we have to configure the fonts. Am I right and how can I configure those fonts?

    Thanks in advance,

    Peter

Comments are closed.