Upload Files as Attachment using Apex Salesforce

Files replaced Attachments in Salesforce.  Now any type of document upload becomes part of Files/Content in Salesforce. With all the other advantages over Attachments, the best one is Files can be shared across objects, means having a attachment with multiple parents.

In lightning experience, any attachment upload is uploaded as files after Winter 16.  But in salesforce classic you need to go to files settings and check “Files uploaded to the Attachments related list on records are uploaded as Salesforce Files, not as attachments” to make this happen. From then onwards Attachments will be uploaded as Files from classic too.

We all being uploading attachment in different ways one and of the ways is via Apex. Now how to upload Files as Attachment using Apex ? It is very simple you just need to understand the object relations and thats it.

ContentDocument

This object record you don’t create. It gets created when you create Content Version who is child of ContentDocument. But Id of this record will be required to do other stuff.

ContentVersion

This is where you attachment goes, you need to create this record in same way as you used to do for attachments

String yourFiles = 'Lets assume this is your binary string of the files';

ContentVersion conVer = new ContentVersion();
conVer.ContentLocation = 'S'; // S specify this document is in SF, use E for external files
conVer.PathOnClient = 'ionicLogo.png'; // The files name, extension is very important here which will help the file in preview.
conVer.Title = 'Proposal '; // Display name of the files
conVer.VersionData = EncodingUtil.base64Decode(yourFiles); // converting your binary string to Blog
insert conVer;

This will insert your files but it will still not be visible under Attachment/Files related list. For that you need to create

ContentDocumentLink

This will share the files with users, records, groups etc. You can create multiple records to attach the same files under multiple records

// First get the content document Id from ContentVersion
Id conDoc = [SELECT ContentDocumentId FROM ContentVersion WHERE Id =:conVer.Id].ContentDocumentId;

//Create ContentDocumentLink
ContentDocumentLink cDe = new ContentDocumentLink();
cDe.ContentDocumentId = conDoc;
cDe.LinkedEntityId = yourObjectRecord.Id; // you can use objectId,GroupId etc
cDe.ShareType = 'I'; // Inferred permission, checkout description of ContentDocumentLink object for more details
cDe.Visibility = 'InternalUsers';
insert cDe;

This will create files under your object records.

26 thoughts on “Upload Files as Attachment using Apex Salesforce

  1. So I want files to be converted to attachments, but I’m having a bit of trouble setting this up. Would this be an Apex Class or Apex Trigger? If it’s a trigger, would I need to create code for every object in Salesforce? Is this what the code should look like?

    String yourFiles = ‘Lets assume this is your binary string of the files’; (what should go here?)

    ContentVersion conVer = new ContentVersion();
    conVer.ContentLocation = ‘S’; // S specify this document is in SF, use E for external files
    conVer.PathOnClient = ‘ionicLogo.png’; // The files name, extension is very important here which will help the file in preview.
    conVer.Title = ‘Proposal ‘; // Display name of the files
    conVer.VersionData = EncodingUtil.base64Decode(yourFiles); // converting your binary string to Blog
    insert conVer;

    // First get the content document Id from ContentVersion
    Id conDoc = [SELECT ContentDocumentId FROM ContentVersion WHERE Id =:conVer.Id].ContentDocumentId;

    //Create ContentDocumentLink
    ContentDocumentLink cDe = new ContentDocumentLink();
    cDe.ContentDocumentId = conDoc;
    cDe.LinkedEntityId = yourObjectRecord.Id; // you can use objectId,GroupId etc
    cDe.ShareType = ‘I’; // Inferred permission, checkout description of ContentDocumentLink object for more details
    cDe.Visibility = ‘InternalUsers’;
    insert cDe;

    Like

  2. Hi, can we attach the file and doc into the Notes and attachment object as a related list of the Custom Object? By using this block of code.

    Like

  3. Could you please help to bulkify the code as I am trying to insert attachment via Batch and then converting to Content Version and CDL

    Like

    1. Please try below code:

      Note :for file preview from record to get working we need to fetch ContentDocumentId from ContentVersion object.Pass single or list of ContentDocumentId with and sObject id and check in the Object record.

      Public static void insertAttachments(List docIDs,String caseId){ System.debug(‘docId=apexcls’+docIDs); List contentDocumentLinks = new List();
      ContentDocumentLink contentDocumentLink=new ContentDocumentLink(); try{ List contentVersionsLst=[select id ,ContentDocumentId from ContentVersion where ContentDocumentId IN: docIDs] ;
      if(contentVersionsLst.size()!=null){ for(ContentVersion contentVersion : contentVersionsLst){ contentDocumentLink = createContentDocumentLink(contentVersion.ContentDocumentId,caseId);
      contentDocumentLinks.add(contentDocumentLink); } } insert contentDocumentLinks;
      } catch(Exception e) { System.debug(LoggingLevel.ERROR,’####ERROR:’+e.getMessage()); } }

      Like

  4. Hi Vivek, thank you for your blog post. I believe it may get me closer to what I am trying to do. If you could comment on feasibility of it, I’d appreciate. The short version of it is, I have an Apex controller that shares data with an lwc. The Apex controller gets its data from a REST API, which is capable of sending the content of image files as encoded strings. I’d like to receive the image data in the Apex controller, write it to a file, and then send a link to the file to the lwc so that in can be included in an image tag, e.g. . Does all of this sound doable to you, and what other aspects fo APex development/SF would I need to become familiar with? Thank you!

    Like

    1. Yes, it is doable. Just insert the file and when you query the file again or if you have the ids you can create the link and send it to lwc as string. Just query already existing link and try to replace the ids.

      Like

  5. Hi,

    I’m trying to upload an image from mobile app built using iOS mobile sdk taking your doc as reference. In your document while creating ContentVersion you’re making use of String yourFiles = “”. What is that exactly? Is that my image converted to a binary string? If so again we are decoding that at conVer.VersionData = EncodingUtil.base64Decode(yourFiles) right? Can you elaborate more on these 2 lines once?

    Like

  6. Hi
    I am using
    Blob yourFiles = Blob.valueOf(‘All your info goes here monday’);
    ContentVersion conVer = new ContentVersion();
    conVer.ContentLocation = ‘S’;
    conVer.PathOnClient = ‘test’+’.’+’pdf’;
    conVer.Title = ‘Proposal1Monday14’;
    conVer.VersionData = EncodingUtil.base64Decode(s);
    conVer.origin = ‘H’;
    insert conVer;
    Id conDoc = [SELECT FileExtension ,ContentDocumentId FROM ContentVersion WHERE Id =:conVer.Id].ContentDocumentId;
    ContentVersion cv =
    [SELECT Title, FileExtension, VersionData, ContentDocumentId,
    ContentLocation, FileType
    FROM ContentVersion
    WHERE ContentDocumentId = :conDoc
    AND IsLatest = true];
    //Create ContentDocumentLink
    ContentDocumentLink cDe = new ContentDocumentLink();
    cDe.ContentDocumentId = conDoc;
    cDe.LinkedEntityId = ‘XXXXXXXXX’;
    cDe.ShareType = ‘I’;
    cDe.Visibility = ‘InternalUsers’;
    insert cDe;
    The above snippet does create a PDF type attachment. But does not give a preview. And even when I download and try to open the file using a Online viewer – it says Error loading File.

    Like

  7. Hi, I have my image being inserted through apex as a File object as shown above however my inserted record (which is a .png image) doesn’t contain the image seems the URL is a little wrong any help would be greatly appreciated

    Like

  8. I want to validate the file format of the file uploaded on file related list on record detail page and on the object record feed. Which content object to use to achieve this. Contentversion, contentdocument or contentdocumentlink.please help me on this.

    Like

    1. Hi Sukruti,

      It depends on how you are uploading the document. If from Lightning component you can restrict certain type by adding validation on JavaScript

      Like

  9. I want to validate the file format of the file uploaded on file related list on record detail page and on the object record feed. Which content object to use to achieve this. Contentversion, contentdocument or contentdocumentlink. Please help on this.

    Like

  10. Good article.

    pardon me if i am wrong, I have one question. In this article, you are only written for creating files not the conversation of files to attachments.

    Like

  11. Hi I have a question about this. I understood how we add files and document link through apex. I’m trying to create a file with VF page rendered as PDF, file is created but file type is coming as unknown any idea how to resolve this.

    cv.VersionData = pr.getContentAsPDF();

    Like

Leave a comment