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
SuriSuri 

Download Attachment from Sites??

Hi

 

I have a Contact in my Salesforce org. and have an Attachment (a PDF file) associated to that Contact.

 

Is it possible to download this PDF file from a Site Page?

 

I am able to query and Display the name of the file on my Site page, but want to know if there's a way to download the file.

 

Thanks,

 

Suri

Best Answer chosen by Admin (Salesforce Developers) 
Ron WildRon Wild

You might also want to try the $Action.Attachment.Download statements

 

 <img src="{!URLFOR($Action.Attachment.Download, attachmentId)}" />

 

 <a href="{!URLFOR($Action.Attachment.Download, attachmentId)}" >blah blah</a>

All Answers

wesnoltewesnolte

Hey

 

I've done something similar although in my case it's a document I've uploaded. I simply use the following String:

 

/servlet/servlet.FileDownload?file= 

 

I then concatenate the id of the document onto the end of said String, and use that string as the 'value' on an outputLink.

 

Cheers,

Wes 

SuriSuri

Hi

 

Thanks a lot. :)

 

It worked!

Ron WildRon Wild

You might also want to try the $Action.Attachment.Download statements

 

 <img src="{!URLFOR($Action.Attachment.Download, attachmentId)}" />

 

 <a href="{!URLFOR($Action.Attachment.Download, attachmentId)}" >blah blah</a>

This was selected as the best answer
BulentBulent

Ron's suggestion is the way you should use.

 

the following is the best way to code:

 

<apex:image url="{!URLFOR($Action.Attachment.Download, attachmentId)}" />

 

 

 

 

Message Edited by Bulent on 07-16-2009 11:07 AM
bromerobromero

Hi, I also need to do this.

Should I use a Static Ressource or a Document? The number of files I need to be able to download can potentially increase over the 250Mb limit for Static Ressources...  But I don't want to hard-code IDs intostrings.

 

Thanks

BulentBulent

You don't need to hard code ids.

if you use documents or attachments our can populate ids by code. Documents and attachments are cached for 10 minutes and the updates will be reflected 1 minutes later

 

if you use static resource they are cached for a day and the updates are reflected instantly (if the page is cached then when the page cache expires) because $Resource.resource name generates a time stamp as part of the url 

 

there are individual file size limits for both. If you use documents or attachments then you can use all the storage available for your organization. If you use static resources then there is a cap limit for static resources.

 

but if you are planning to serve large files daily then beware about the 24h rolling bandwidth limit (40GB for active orgs), even though you can cache them they need to be served at least once, so you might want to decide you store the large files in salesforce vs. somewhere else based on your use case and usage.  

acl5acl5
I've managed to view/download Attachments, but can I download Documents (files stored as Document Objects) from my Site?
TomSnyderTomSnyder

Is the FileDownload servlet still accessible from Sites.  I get redirected to Authorization Required when trying to download an attachment that is owned by the Sites Users,  

 

In addition no log is recorded in the 'Debug Log' for this action.

 

VF code:

 

<apex:outputLink value="{!URLFOR($Action.Attachment.Download, att.Id)}" id="theLink" target="_blank">{!att.Name}</apex:outputLink>

 

 

 

 

 

 

 

 

BulentBulent
sites must  to have read access for the parent object and the parent record. It should work.
saharisahari

I can't have a customer portal user view/donwload attachments. Does anyone ahve a workaround for this?

If i hardocde the contactId in the controller, thery are visible in the customer portal. But if I change the code to read the currentuser and get the contact id related to the customer portal user and pass it...,

It shows empty table of attachments..

Any help would  be greatly appreciated.

saharisahari

In my case, the parent obj is contact and I see the customer portal user profile has the read access for it.

But yet, it is not allowing to download.

 

Thanks in advance! 

TomSnyderTomSnyder

Make sure the portal user has visibilty to the contact record.  Just cause the Profile is granted read on the Object does not mean it has visibility.  visibilty is typically controlled by the OWNER of the contact record and sharing rule(s) (unless you are using APEX custom sharing, or territory Mgmnt)

 

Tom

saharisahari

I am trying to display some other fields from contact record. They all work fine. This means the contact record is visible to the portal user.  Please correct me if I am wrong.

And about the sharing rules. Do we have to setup some sharing rules for this? If so, Can you please explain me in detail?

I am sorry if I am asking too basic questions? I am a beginner in development.

 

Thanks

TomSnyderTomSnyder

>>Please correct me if I am wrong.

 

if you are using 'with sharing' in your class when you [SELECT.. your contact]  then I would say that your portal users does have access. 

 

try pasting the contactId in the url when logged in as Portal user:  Ex: https://na?.salesforce.com/003000000000012

if you can see it you have access,  and should be able to add an attachment.

 

-Tom

saharisahari

I added with sharing in my class.. no Luck yet!

And I am unable to login into the salesforce instance as a customer portal user. While I can login into customer portal with the same credentials.

 

Here is my class:

 

public with sharing class InputFileController {
   
    public List<Attachment> a{ get; set; }
    public void met(){
    String Uid=Userinfo.getUserId();
    User u = [SELECT Id, Name, Contact.Id FROM User where id=:Uid];
    a = [select id, name, contentType, bodylength  from  Attachment  where parentid=:u.contact.Id ];
      }
    
}

 

public with sharing class InputFileController {   
    public List<Attachment> a{ get; set; }  

    public void met(){  

 String Uid=Userinfo.getUserId();  

 User u = [SELECT Id, Name, Contact.Id FROM User where id=:Uid];
    a = [select id, name, contentType, bodylength  from  Attachment  where parentid=:u.contact.Id ];    

 }
    }

 

 

 

And the vf page snippet:

 

 

  <apex:outputLink 

      value="/servlet/servlet.FileDownload?file={!att.id}">{!att.name}</apex:outputlink>

                                                </apex:column>

I am able to display the names of attachmenst in the page but when i click on the link,  it does nothing.

 

 

saharisahari

Also 

When I have added with sharing in my class,

Now it does'nt display even the names. 

TomSnyderTomSnyder

this confirms you dont have visibility on that record as I suspected.  do some research on 'sharing rules' , custom sharing etc.. and general sfdc security so you can properly grant access to to your portal users using sharing rules, or other means that do not expose your sensitive data.

 

The 'with sharing' clause means that the class will allow access only to the records which the current user has visibility.  where as removing it acts as a system user.  do some research here also cause it does act differently depending on the usage of a custom or standard controller

 

No matter if you use 'with sharing' or not downloading an attachment will still requires the current user to have visibility to the parent obj.

 

Profile Security:   Object level

Sharing:  record level security

 

Hope this helps,  Tom

saharisahari

I have a question in my mind..

Now that I have'nt set up any sharing rules yet. 

But I am still able to see the list of attachments and also I am able to display several fields from its parent obj. in my case it is contact record.

The only prob I am facing is that, when I click on the link to download the attachment, it does 'nt get downloaded

How is this possible without having setup any sharing?

saharisahari

I also defined a sharing rule:

contact owned by all intwernal users and shared with all customer portal users

WesNolte__cWesNolte__c

What happens when you click it? Can you give us the page code please.

 

Wes

saharisahari

When we click that link, it goes to the insufficient previliges page.

hew is the vf code snippet

 

 <apex:pageBlockTable value="{!a}" var="att">
                           <apex:column headerValue="Title">
                           <apex:outputLink value="/servlet/servlet.FileDownload?file={!att.id}">{!att.name}</apex:outputlink>
                           </apex:column>
                           <apex:column headerValue="Length">
                           <apex:outputText >{!att.bodylength}</apex:outputText>
                           </apex:column>
                    </apex:pageBlockTable>

 

 <apex:pageBlockTable value="{!a}" var="att">                

          <apex:column headerValue="Title">                  

                    <apex:outputLink value="/servlet/servlet.FileDownload?file={!att.id}">{!att.name}</apex:outputlink>          

          </apex:column>            

           <apex:column headerValue="Length">          

                   <apex:outputText >{!att.bodylength}</apex:outputText>                

          </apex:column>

 </apex:pageBlockTable>

 

and the controller code to retrieve attachements:

 

 

a = [select id, name, contentType, bodylength  from  Attachment  where parentid=:u.contact.Id ];

Any idea?

 

BulentBulent

I don't recommend hard coding the download url

use the following line to generate the link:

 

 

{!URLFOR($Action.Attachment.Download, att.Id)}

 

I'm guessing your site has a path and with your link you are using relative url without the path. If you use the above code URLFOR will take care of the path and the $action.download will always generate the correct download url.

 

saharisahari

No luck yet.

 

                           <apex:outputLink value="{!URLFOR($Action.Attachment.Download, att.Id)}">{!att.name}</apex:outputlink>
                          

 

 

 <apex:outputLink value="{!URLFOR($Action.Attachment.Download, att.Id)}">{!att.name}</apex:outputlink>                          

BulentBulent

can you post your site/page url?

saharisahari

Here is the site/page url to this corresponding page:

 

http://angelmedflight.dev101109.cs0.force.com/inputfilecontroller

 and then the link to download is 

 

 





 

WesNolte__cWesNolte__c

You'll need to give us credentials to log in with.

BulentBulent

I'll check your setup (I don't need user name, password) and post my feedback later today.

saharisahari

Alright!

 

Thank you all for the immediate responses.

BulentBulent

did you plan to expose this page (http://angelmedflight.dev101109.cs0.force.com/inpu tfilecontroller) after the authentication? Seems like it's finding the current user's contact info (in site context, guest user is the user and no contact is associated with the gust user) then listing the attachments for the contact.

 

 

saharisahari

We are not allowing the cutomer portal users to self register. We give our customers username and passwords and then we create a contact record for them.

And yes this page is using the current user's contact info. and attachments related to them.

We are enabling them to submit attachments from customer portal, and it works fine. So uploading is not a prob and listing these attachments is also not a prob.

But only problem is that we are unable to download the attachment.

And I inquired with the  salesforce support. they also escalated the case and finally their response is that we cannot get this functionality done.

So looking to see if there is any other workaround.

BulentBulent

here is my demo site that this use case is working via sites

 

http://sitesdemo.force.com/realty/listing?id=a0h30000002KaqhAAC

I have a custom object where I define real estate listing details. And the above page creates the links for the attachments on listing records.

 

here is the page code:

 

<apex:page title="Big Cloud Realty" showHeader="false" controller="ListingController">
    <apex:composition template="bigCloudTemplate">
        <apex:define name="mainContent">
        
            <apex:outputPanel layout="block" styleclass="block" style="float:left;display:inline;width:445px">
                <div class="blockTitle"><span class="blue">Listing</span> Details</div>
                <div class="blockBody">
                    <h2>
                        {!listing.Address__c}<br/>
                        {!listing.Neighborhood__c}
                    </h2>
                    <p/>
                    <b>{!listing.Tag_Line__c}</b><br/>
                    {!listing.Description__c}
                    <p/>
                    Age: {!ROUND(listing.Age__c,0)}<br/>
                    Bedrooms: {!ROUND(listing.Bedrooms__c,0)}<br/>
                    Bathrooms: {!ROUND(listing.Bathrooms__c,0)}<br/>
                    Status: {!listing.Status__c}
                    <p/>
                    <apex:outputLink value="{!$Page.inquire}?lid={!listing.Id}">Inquire about this listing</apex:outputLink>
                    <p/>
                    <apex:outputPanel layout="none" rendered="{!NOT(ISPICKVAL($User.UserType,'Guest'))}">
                        <apex:form >
                            <apex:commandLink action="{!watch}">Watch this Listing</apex:commandLink>
                        </apex:form>
                        <p/>
                    </apex:outputPanel>
                    Pictures:<br/>
                    <apex:repeat value="{!pictures}" var="pic">
<br/>
                         <apex:outputLink value="{!URLFOR($Action.Attachment.Download, pic.id)}">{!pic.name}</apex:outputLink>
                    </apex:repeat>
                    <p/>
                </div>
            </apex:outputPanel>
                    
        </apex:define>
    </apex:composition>
</apex:page>

 

 

and here is the controller code:

 

public class ListingController {
    
    private String listingId {
        get {
            return ApexPages.currentPage().getParameters().get('id');
        }
    }
    
    public Listing__c listing {
        get {
            return [SELECT Id, Name, Address__c, Age__c, Agent__r.Name, Asking_Price__c, Bathrooms__c,
                Bedrooms__c, Description__c, Neighborhood__c, Status__c, Tag_Line__c, Master_Picture_ID__c
                FROM Listing__c WHERE Id=:listingId LIMIT 1]; 
        }
    }
    
    public Attachment[] pictures {
        get {
            return [SELECT Id, name FROM Attachment WHERE ParentId=:listingId ORDER BY CreatedDate ASC];
        }
    }
    
    public PageReference watch() {
        WatchItem__c watchItem = new WatchItem__c(Listing__c = listingId);
        Insert watchItem;
        return null;
    }
    
    testmethod static void test() {
        User agent = TestSupport.getAgent();
        Listing__c l = TestSupport.createListing(true, agent.Id);
        
        Test.setCurrentPage(new PageReference('/listing?id=' + l.Id));
        ListingController lc = new ListingController();
        
        Listing__c controllerListing = lc.listing; 
        System.assertEquals(lc.pictures.size(), 0, 'Should not have any pictures attached to this listing.');

        lc.watch();     
    }
}

 

 

vasuvasu

Hi All,

 

I want to download workspace content files from sites , I s there any possibility to do

 

Any one can suggest me or give any sample code?

 

Thanks

Vasu

saharisahari

Hi

 

I tried your code also. But dint work. I suppose , in your case a guest user must be acceessing this page. But am using a Customer Portal Authenticated User.

Also I have a cloned aprofile from the standard   "CP  standard user Profile"  and the I have given this profile CRUD permissions to this custom obj.

And still I am unable to get it.

I tried all possibel ways I knew. 

 

Anywasy I really appreciate your help. Thanks

saharisahari

@Bulent

 

Hey thanks for the solution. I was going through one of theother forums where you have given the solution for this problem.  The custom obj I was referring to was in development status. And I dint change it to deployed before accessing it from the sites. And that was the problem.

 

And now I realise that.

I appreciate for all the help.

Thanks

V AnandV Anand

Hi........

How to download attachments from sites.. when I am trying to download attachments from site I got insufficient privilages 

error. When I logged in al "Preview as admin" I got this error ..."FIle not allowed for profile"..

I set read and write permissions to contact object. Please help me