Recently I had to do a little project where users wanted to display a list of photos associated with a custom object. I decided to take advantage of what Salesforce already provides: attachments. I designed a custom visualforce page to show the attachment as photos. In this post I will show a little example of how to accomplish this using an extension controller and a visualforce page.

Let’s work with a simple example: suppose we want to implement a database of movies in Salesforce and, besides the typical movie attributes, we want to show photos of the movie (movie poster, scenes, etc.) The end result is something like this:

Movie with Photos

As you can see from the image, we are displaying a list of photos below the movie fields. The first thing we need to do is enable attachments for our custom object.

Object settingsWe will select the “Add Notes and Attachments related list to default page layout” on object creation. This will enable the object to have attachments. We can add as many attachments as we want (or as the Salesforce space limitations allow us). Once the custom object is created, we will be able to add attachments using the standard page layout that is created as part of the object.

Let’s us create a movie and add some attachments to it. In the example, I’ve set up some basic fields for a movie: name, genre, storyline and release date (this is enough for this example). I’ve created a sample movie (I’m a big fan of the Alien franchise) and added some attachments to it:

The movie layout with attachments

Now, for the fun part: we will create a custom visualforce page to show those attachments as photos. Let’s start by creating a new visualforce page by typing https://<salesforceurl>/apex/Movie?id=<someMovieId>. This will create a new Apex page called Movie, from scratch. Add the following markup to the visualforce page:

<apex:page standardController="Movie__c" extensions="MovieControllerExtension">
    <apex:detail relatedList="false"/>
    <apex:pageBlock >
        <apex:pageBlockSection title="Photos ({!totalPhotos})" collapsible="false">
            <apex:repeat value="{!photos}" var="photo">
                <apex:image url="{!URLFOR($Action.Attachment.Download, photo)}" width="50px" height="50px" />                    

This is a very simple page: we’re leveraging on the apex:detail tag to have all the movie details and then we create a page block to list the photos (the attachments). The magic happens in line 6, where we use the special action Download to actually download the attachment at run time and display it as the source of the apex:image tag. We do all this inside the apex:repeat tag to cycle through all the attachments for the current movie object. Notice how we are using a controller extension called MovieControllerExtension. This extension provides two properties: totalPhotos and photos. The photos property is just a list of Ids for each of the attachments associated with the object. This is the code for the controller extension:

public with sharing class MovieControllerExtension {

    private ApexPages.standardController controller;
    private Movie__c movie;

    private List<Id> photoIds; 

    public MovieControllerExtension(ApexPages.StandardController controller) {
        this.controller = controller;
        this.movie = (Movie__c)controller.getRecord();

    public List<Id> photos {
        get {
            if(photoIds == null) {
                photoIds = new List<Id>();
                for(Attachment att : [select Id from Attachment where ParentId = :movie.Id]) {
            return photoIds;
    public Integer totalPhotos {
        get {
            return photos.size();

Lines 19 and 20 show how the attachment ids are retrieved from the database and added to the photos property.

And this is it! we get a nice list of all the photos for the movie by leveraging the attachment records associated to our custom object.


Comment by Scott

Excellent job of presenting the concept - perfect for what I needed! Thank you!