function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
MJ09MJ09 

Get the URL of a Static Resource from Apex code

How can I determine the URL of a static resource from my Apex code?

 

I'm looking for the equivalent of the VisualForce $Resource variable, but one that I can use from with Apex code.

 

Thanks!

mtbclimbermtbclimber

There isn't one.

 

What is your use case? 

 

Thanks,

MJ09MJ09

I have a VisualForce controller that builds a relatively complex HTML string that gets rendered on the page by an outputText component. The HTML string includes an IMG tag that references an image stored as a static resource.

I know I could build the HTML in the page using components, but it seems simpler and more straighforward in my case to build it using in the controller Apex.

 

I could also imagine a situation where a web service might want to return the URL of a static resource.

 

mtbclimbermtbclimber

What I've seen done in this case if I understand you correctly is to use one static resource - a structured archive, e.g. a zip file - and dynamically pluck an image out of it based on your rules.

 

I did something similar in my intro to Visualforce article here regarding the mobile browser check. Search for "mobileSample" within that page.

MJ09MJ09

On other pages, I've used URLFOR in the value of a component on a VF page to get the URL of an image that's in a zip file, so I know how to do that. Even with that, I'm still left with the question of how to write Apex code that gets the URL of the static resource, whether it's in a zip file or an image.

 

mtbclimbermtbclimber
Are you generating markup in apex as a string?
MJ09MJ09

Yup. I have a VisualForce controller that builds a relatively complex HTML string that gets rendered on the page by an outputText component. The HTML string includes an IMG tag that references an image stored as a static resource.

 

I know I could build the HTML by putting a whole bunch of components in the VF page and then using "rendered" attributes to pick the ones I want to include in my final result, but given the complexity of the HTML markup that I'm producing, it seems a lot easier and more straightforward to build the HTML markup in Apex.

mtbclimbermtbclimber

Ok this is what I missed, not really a use case we've targeted which is why you don't see an apex type for static resources that support a getUrl() method on them.

 

You could use CSS to define your image and in your code apply a class name for the appropriate style.

MJ09MJ09

I've got a work-around that's working now for my specific case, but I could see situations where it would be useful to be able to get the path of a static resource in Apex.

 

In my case, my Apex code is running in the controller for a custom component. I added an attribute named Pathname to the custom component. The main VF page supplies a value of {!$Resource.myImage} for that attribute, and the controller for the custom component gets the value of that attribute, thereby getting the URL of the image. This works in my case, where my Apex code just happens to be in a custom component's controller, so I'm OK for now, but I could see it being useful for Apex code in general (for example, for a web service method) to be able to get that URL.

 

Thanks for your very prompt responses!

 

MJ.

Message Edited by MJ09 on 03-03-2009 10:07 AM
Ron WildRon Wild

I just ran across this blog Ryan Marples wrote that seemed relevant:

 

http://wiki.developerforce.com/index.php/Static_Resources

 

Scroll down to the section on getting static resource references from Apex ...

Message Edited by Ron Wild on 03-14-2009 10:02 PM
mtbclimbermtbclimber
That article is still under review and the method described to generate the URL is not supported. It may work today in some situations but as with any reverse-engineered code, it is all subject to change without notice.
MJ09MJ09

Shoot! And there I was getting all excited that there was a way to get the URL with Apex code after all!

 

Two suggestions:

 

1. Andrew, could you please update the Wiki article (http://wiki.developerforce.com/index.php/Static_Resources) to reflect your comments that this approach for getting the URL isn't officially supported or recommended?

 

2. I assume the part that's subject to change is not the StaticResource SObject, but rather the notion that Static Resource URLs will always be based on LastModifiedDate. If that's true, how about if Salesforce adds a formula field to the StaticResource object that returns the URL for each resource? That way, all us developers will be able to rely on the formula to get the URL, and if you change the way URLs are composed, you can change the formula accordingly, without impacting developers?

 

 

mtbclimbermtbclimber
1. As I mentioned the article is still under review and I've asked for the requisite changes already.  It hasn't been "published" in the sense that a blog entry has been released pointing to it or other higher visibility reference.  It probably shouldn't have been discoverable until the review was completed, however. Sorry for the confusion that has caused here.

 

2. That is always our approach to such things and why we continually caution against various forms of screen-scraping or other reverse-engineering techniques.  In the case of StaticResources we might:

 

  • change the path to not be /resource
  • alter the versioning mechanism
  • add something to the path

 

Also depending on the context /resource might not even be correct today, e.g. specific sites configurations.

 

As for static resource URLs from Apex, this is something we're working on in conjunction with a dynamic page generation capability that *hopefully* will supplant any string based html generation in Apex which is currently the only use case I've heard for generating SR URLs in Apex.

goabhigogoabhigo

Is this solved now?

 

How do I access static resource file in apex class?

zachelrathzachelrath

You can query the StaticResource object from Apex by Name, Id, etc., and this will return most of the information you might need --- for instance, the Body of the Static Resource. What you cannot get at (from Apex) is the URL path to the most current version of the Static Resource, which is what MJ was trying to do.

 

Andrew, another use case for needing a Static Resource's URL in Apex would be trying to dynamically parse (in Apex) individual files with a Static Resource that's a ZIP file. For instance, if I wanted to take a whole pile of CSV files containing SObject records, zip them up into a Static Resource, and then parse each individual file within the ZIP bundle dynamically from within Apex. Here's what would be awesome:

 

// ***(NOT CURRENTLY POSSIBLE)***
String statResourceURL = [select URL from StaticResource where Name = 'SampleData' LIMIT 1].URL;

// Get a PageReference corresponding to the location 
// of an individual file within a ZIP file
// uploaded as a Static Resource
PageReference pageRef = new PageReference(statResourceURL + '/Account.csv');

// Get the content of this PageReference as a Blob
Blob csvBlob = pageRef.getContent();

// Proceed with parsing the CSV file...

 

metaforcemetaforce

Looks like I have a temporary working solution for the time being. The static resource is used in the Visualforce as:

 

URLFOR($Resource.<name>,'<path>')

 

which evaluates to the URL:

 

/resource/<timestamp>/<name>/<path>

 

So if you have the Static Resource name stored somewhere in the org, say in a custom setting, then you can create the URL in Apex, by just creating the URL string above and replacing <timestamp> with the static resource's milliseconds of its SystemModstamp value using the getTime() function of a DateTime type variable.

 

StaticResource s = [Select Id, SystemModstamp from StaticResource where Name = someName];

String timestamp = String.valueOf(s.SystemModstamp.getTime());

 

Let me know if it doesn't work for you.

zachelrathzachelrath

Yes, metaforce's solution using SystemModstamp is the way to do it. Here's a general-purpose method which supports namespaced-resources as well:

 

public static String GetResourceURL(String resourceName) {

List<StaticResource> resourceList = [
   SELECT Name, NamespacePrefix, SystemModStamp 
   FROM StaticResource 
   WHERE Name = :resourceName
];
                    
if (resourceList.size() == 1) {
   String namespace = resourceList[0].NamespacePrefix;
   return '/resource/' 
      + resourceList[0].SystemModStamp.getTime() + '/' 
      + (namespace != null && namespace != '' ? namespace + '__' : '') 
      + resourceName; 
} else return '';

}

 

zachelrath

notThatShanenotThatShane

Wow -- is there really not a more direct way of doing this??  Oh my.

 

I'm trying to pull a salesperson's signature image (jpg) file into a visualforce page.  The signature images are stored as individual static resources, and the name of each static resource is stored in a custom field of the user object, Signature_Image.  I'm trying to reference the image like this:

 

Apex class: (relevant portions only)

 

public Opportunity theOpp {get; set;}

theOpp = [Select Id, Owner.Signature_Image__c From Opportunity Where Id = :controller.getRecord().Id];

String sig = '$Resource.' + theOpp.Owner.Signature_Image__c;

 

...and on the visualforce page...

 

<apex:image value="{!sig}" width="100%" height="auto"/>

I also tried

 

<apex:image value="{!URLFOR(sig)}" width="100%" height="auto"/>

 ...but neither one worked.

 

Maybe I shouldn't be storing the signature images as static resources??  Any suggestions would be appreciated.

 

Thanks   :)

zachelrathzachelrath

Actually since you're within Visualforce there's a much easier way of doing it. Assuming that you have a Controller variable sig equal to the name of the signature's StaticResource, e.g. 

 

public Opportunity theOpp {get; set;}

theOpp = [Select Id, Owner.Signature_Image__c From Opportunity Where Id = :controller.getRecord().Id];

String sig = theOpp.Owner.Signature_Image__c;

Then you can dynamically access the Resource like this:

 

<apex:image value="{!URLFOR($Resource[sig])}"/>

 However, I would NOT use StaticResources to store Signature Images, I would use Attachments. Attachments are much better suited to this purpose. For instance, assuming that the Signature_Image__c field on the User object contains the Id of an Attachment containing as its body an image of that user's signature, then you can do this on a Visualforce Page with the Opportunity StandardController to display the signature:

 

<apex:page standardController="Opportunity">
<apex:sectionHeader title="{!Opportunity.Name}"/>
<apex:image value="{!URLFOR($Action.Attachment.Download,Opportunity.Owner.Signature_Image__c)}"/>
</apex:page>

 

or, if you already have the image as a variable, e.g. signatureAttachmentId, in your controller, then:

 

<apex:page standardController="Opportunity" extensions="OppExtensionController">
<apex:sectionHeader title="{!Opportunity.Name}"/>
<apex:image value="{!URLFOR($Action.Attachment.Download,signatureAttachmentId)}"/>
</apex:page>

 

 

 

Christian Juul MikkelsenChristian Juul Mikkelsen
I know that this is not exactly what you asked for, but it seems that it might help some of the others in this thread. you can reference a static resource from a visualforce page by setting a string to a value in the controller and then use the string to get the static resource.
//from controller:
// the string should have a get method so that it could be access from the page. 
string teststring = 'myStaticResource'

// access the static resource from the page this would get the static resource named myStaticResource:
"{!$Resource[teststring]}"

Hope that is helps some. If someone finds a way to the the url for a static resource from the controller then I would be very happy to know! I am also building all html as a string in the controller and need the static resource url.
 
Phil WPhil W
This is a really old thread but still doesn't mention the use of PageReference.forResource(resourceName) or PageReference.forResource(zipName, path) to obtain the URL of a static resource from Apex code.

Now it does :)