Pages

Monday, October 26, 2015

Salesforce: Attach File with code

In previous blog, we discussed about how to attach file to a record using "File" and "Attachment". As you read in that blog, to attach file as Attachment, user need to have Edit permission on the parent record.

In some use cases, permission to edit record is not ideal, example: support users not supposed to edit an opportunity record, but they just need to read the opportunity and may need to attach file. Chatter File is a great option for this limitation, but for some reasons, company may just want to use Attachment, rather than split between Attachment and File.

In this blog, we will introduce to use Apex class for user to upload file as Attachment. Remember that when using Apex class, by default it will not check user permission for the record, as long as user able to open the record and the user profile have access to the Apex class and Visualforce page.

So, here are few items and steps needed to built custom attach file functionality as Attachment, in this example, we are going to use Opportunity object:

1. Create Apex Class
This is the core program to upload the file to Salesforce and attached to the parent record.
1:  public class TicketAttachment   
2:  {  
3:    /* Start - Variables */  
4:    public Id recId         {get;set;}   
5:    public Attachment objattachment {get{  
6:                      if(objattachment == null)  
7:                        return objattachment = new Attachment();  
8:                      return objattachment;    
9:                     }set;  
10:                   }  
11:    /* End - Variables */  
12:      
13:    /* Start - Constructor */  
14:    public TicketAttachment(ApexPages.StandardController ctlr)   
15:    {   
16:      recId = ctlr.getRecord().Id;      
17:    }   
18:     /* End - Constructor */  
19:       
20:    /*  
21:      * MethodName    : upload  
22:      * param       : -  
23:      * Description    : This function used to upload Attachment and redirect the user back to parent  
24:    */  
25:    public PageReference upload()   
26:    {  
27:      objattachment.OwnerId = UserInfo.getUserId();  
28:      objattachment.ParentId = recId;  
29:      try   
30:      {  
31:       insert objattachment;  
32:      }   
33:      catch (DMLException e)   
34:      {  
35:       ApexPages.addMessage(new ApexPages.message(ApexPages.severity.ERROR,'Error uploading attachment'));  
36:       return null;  
37:      }   
38:      return new Pagereference('/'+recId);  
39:    }  
40:      
41:    /*  
42:      * MethodName    : cancel  
43:      * param       : -  
44:      * Description    : This function redirect the user back to parent.  
45:    */  
46:    public PageReference cancel()   
47:    {  
48:      return new Pagereference('/'+recId);  
49:    }  
50:  }  



2. Create Apex Text Class
Each Apex class in Salesforce need to have a test class with minimum of  75% test coverage.

1:  /**   
2:  * \arg Description   : Test class for TicketAttachment controller class.  
3:  */  
4:  @isTest  
5:  private class Test_TicketAttachment   
6:  {  
7:    static Opportunity objTicket;  
8:    static PageReference pageRef;  
9:      
10:    //Preparing data for testing the functioanlity  
11:    static testMethod void setUpData()  
12:    {  
13:      objTicket = new Opportunity(Name='SA', StageName='Prospecting', CloseDate=Date.newInstance(2016, 2, 17));  
14:      insert objTicket;  
15:    }  
16:      
17:    //checking for upload functionality  
18:    static testMethod void test_FileUpload()   
19:    {  
20:      Test.startTest();  
21:      setUpData();  
22:      system.debug('==objTicket==='+objTicket);  
23:        
24:      pageRef = new PageReference('/apex/TicketAttachmentVF?id=objTicket.Id');   
25:      Test.setCurrentPage(pageRef);  
26:      pageRef.getParameters().put('id', objTicket.Id);  
27:        
28:      ApexPages.StandardController stdCTR = new ApexPages.StandardController(objTicket);  
29:      TicketAttachment objController = new TicketAttachment(stdCTR);  
30:        
31:      Attachment objAtt = new Attachment(Body = Blob.valueOf('Test Body'), Name = 'Test Attachment', ParentId = objTicket.Id);  
32:      insert objAtt;  
33:        
34:      pageRef = objController.upload();  
35:      //System.assertEquals(pageRef.getUrl(),'/'+objTicket.Id);  
36:        
37:      pageRef = objController.cancel();   
38:      
39:      Test.stopTest();  
40:    }
41:  
42:  }  


3. Create Visualforce Page
This Visualforce page served as user interface for user to upload a file.
1:  <apex:page standardController="Opportunity" extensions="TicketAttachment">   
2:    <apex:sectionHeader subtitle="Attachment Upload Example"/>  
3:    <apex:form enctype="multipart/form-data">  
4:      <apex:pageMessages />  
5:      <apex:pageBlock title="Upload a Attachment">  
6:        <apex:inputFile value="{!objattachment.body}" filename="{!objattachment.name}" id="file"/>  
7:        <apex:pageBlockButtons location="bottom">  
8:          <apex:commandButton action="{!upload}" value="Save"/>  
9:          <apex:commandButton action="{!cancel}" value="Cancel"/>  
10:        </apex:pageBlockButtons>  
11:      </apex:pageBlock>  
12:    </apex:form>  
13:  </apex:page>  



4. Create Custom Button or Link
This is standard Custom Button or Link, select Content Source = Visualforce page


5. Add Custom Button or Link to Page Layout
Custom button or link created will not appear in page layout until you add them.



6. Add Apex Class and Visualforce Page to user profile
Each user need to use apex class and visualforce page functionality need to have apex class and visualforce added to their Profile or Permission Set.



ReferenceSalesforce: Attach File to a Record