The first step is to write your Apex Code (remember to use version 17.0 or higher of the Salesforce API). Here's the code:
public class ImageController {
public ContentVersion myImage {get;set;}
Bird__c bird;
Map
'Species Images' => '058S0000000CaaY'
};
Map
'Species Images' => '012S00000000Kpe'
};
public ImageController(ApexPages.StandardController controller){
bird = (Bird__c)controller.getRecord();
bird = [select Id, Name, Binomial_Nomenclature__c from Bird__c where Id = :bird.Id ];
myImage = new ContentVersion();
}
public PageReference upload(){
if (myImage.PathOnClient != null){
myImage.Title = bird.Name;
myImage.RecordTypeId = contentTypeMap.get('Species Images');
myImage.FirstPublishLocationID = workspaceMap.get('Species Images');
myImage.Bird__c = bird.Id;
insert myImage;
return new PageReference('/'+ bird.Id);
}
else{
return null;
}
}
public PageReference cancel(){
return new PageReference('/' + bird.Id);
}
}
There's a member variable for the Content (myImage), two member maps to get the right IDs for the Workspace and the ContentType, two Page Actions (one to save, the other to eliminate a cul-de-sac and allow the user to return to the Bird layout) and a constructor that fills the Context record and instantiates the ContentVersion.
Now you write a VF Page (also using Version 17.0 or higher of the API). Here's that code (I removed the leading "<"s from the apex tags to allow this to show inline.
apex:page standardController="Bird__c" extensions="ImageController">
apex:pageBlock title="Upload Image">
apex:pageMessages />
apex:form >
apex:inputFile value="{!myImage.VersionData}" filename="{!myImage.PathOnClient}"/>
br />
apex:commandButton action="{!upload}" value="Upload"/>
apex:commandButton action="{!cancel}" value="Cancel"/>
/apex:form>
/apex:pageBlock>
/apex:page>
This is a simple page that uses the Bird object as the standard controller, uses the Apex code we wrote before as the extension and has a form. The form has an inputFile tag to allow you to browse to the image using explorer and two command buttons that call the page actions defined in our previous page.
If you like, you can add to the page action for upload the error condition and put that in your page messages. this allows for elegant trapping when you don't browse to a file. The final step is to wire all this up.
Add a Custom Button to the Bird Object that uses the Visualforcepage as the Content Source

Then add that button to your Custom Object's layout

Note the presence of the button with no image

And upload the image to an instance of your Custom Object using the VF page

And finally, note that the image is there and related to your object instance

And the picture of the picture related to the Bird (a pretty Yellow-crowned Euphonia)

Voila...
P.S. - Note that you'll need to add the Class and the Page to any profiles using this capability, otherwise you'll get the fun 'Insufficient Privileges' puke
9 comments:
Wow... Nice article. I am looking for such a beautiful and steps to create the images in the contact. I think that the fresher like me will able to do it.
Hats off to you. I started following u (senthil_rect) in twitter.
Do you know anything about why there is a maximum file size of 10MB only when uploading content using this custom button, but no limit when adding content directly to the workspace tab?
Karl
I expect it relates to ViewState limitations on the Visualforce page. Uploading through 'Contribute' goes through a Java app (servlet?) using the API rather than native VF and Apex. For one-off uploads, best to use the tools Salesforce provides
G
Hi
Nice post. This has been very helpful to me but i have one question regarding the access.
In the article when adding the member to workspace it has been done manually. Can that be done using API/code? I am implementing this for large org and its not possible to manually add the users or add public group for the users and I am stuck there. Is there any way we can do it through code?
HI,
Good Explanation, and very nice article. Thanks for sharing.
(nara.dotnet@gmail.com)
Hi Gabe,
I stumbled across this post after googling around quite a bit on associating CRM content with Custom Objects. I have a question though. In your example, you set the Bird__c member of the ContentVersion object, however this is not a standard association. Does apex allow you to do this, or how did you get the ContentVersion to allow that relationship with your custom object? Sorry if this is a silly question, all this is pretty new to me.
Thanks!
G
Post a Comment