+ Start a Discussion
Matthew HofmannMatthew Hofmann 

Create and Associate Salesforce File Using Apex

Hello,

I'm creating an Apex class that creates a Salesforce File record and associates it with a parent record. I'm having a problem creating the association (ContentDocumentLink) record.

Here is what I'm doing:
  • Create a ContentVersion record. This creates a ContentDocument record automatically if you leave the ContentVersion.ContentDocumentId field blank. (https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentdocument.htm - "To create a document, create a new version via the ContentVersion object without setting the ContentDocumentId. This automatically creates a parent document record.")
  • Insert ContentVersion record
  • DEBUG: Confirm ContentVersion.ContentDocumentId is set (Here is where the problem is because it is NULL; however if I SOQL query ContentVersion after the Apex completes, ContentVersion.ContentDocumentId is set and the corresponding ContentDocument record exists)
  • Create ContentDocumentLink record (commented out because it fails because ContentDocumentLink.ContentDocumentId is a required field)
  • Insert ContentDocumentLink record (commented out because it fails because ContentDocumentLink.ContentDocumentId is a required field)
Here is the code:
public class FileController {
    
    @AuraEnabled
    public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType, Id contentDocumentId) { 
        base64Data = EncodingUtil.urlDecode(base64Data, 'UTF-8');
        
        ContentVersion cv = new ContentVersion();
        cv.ContentLocation = 'S';
        cv.ContentDocumentId = contentDocumentId;
        cv.VersionData = EncodingUtil.base64Decode(base64Data);
        cv.Title = fileName;
        cv.PathOnClient = filename;
        
        insert cv;
        
        //***This DEBUG statement must return an Id for the rest of the code to work***
        System.debug('contentDocumentId='+cv.ContentDocumentId);               
        
        //ContentDocumentLink cdl = new ContentDocumentLink();
        //cdl.ContentDocumentId = cv.ContentDocumentId;
        //cdl.LinkedEntityId = parentId;
        //cdl.ShareType = 'I';
        
        //insert cdl;
        
        return cv.Id;
    }

    @AuraEnabled
    public static Id saveTheFile(Id parentId, String fileName, String base64Data, String contentType) {         
        return saveTheFile(parentId, fileName, base64Data, contentType, NULL);
    }
}

Does anyone know what I'm doing wrong, not considering, etc?
Appreciate any thoughts and input!
Best Answer chosen by Matthew Hofmann
VineetKumarVineetKumar
Interesting..

Well the culprit in your code is the null value and way you are using it to assign the value to ContentDocumentLink.contentDocumentId.
You should query the content version object again to get the contentDocumentId (which is generated after the parent document is inserted by default because of you passing of null value).
Something like below :
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id =: cv.Id].ContentDocumentId;
cdl.LinkedEntityId = '00590000000a6dP';
cdl.ShareType = 'V';
insert cdl;

As per the salesforce documentation lines higlighted by you, "To create a document, create a new version via the ContentVersion object without setting the ContentDocumentId. This automatically creates a parent document record." it does create the parent document record as expected, but the contentDocumentId is still null in above initialised object. Id doesn't get updated automatically to the object instance. Infact you will have to pull out the corresponding Id as done in the above snippet.

Let me know if this helps.

All Answers

VineetKumarVineetKumar
What happens if you use the below in your code?
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = contentDocumentId;
cdl.LinkedEntityId = parentId;
cdl.ShareType = 'I';

 
Matthew HofmannMatthew Hofmann
Good question. Also I should have been more clear. In this case I'm calling the second method that does not have a contentDocumentId parameter, which in turn calls the first method so contentDocumentId is NULL. 
VineetKumarVineetKumar
Interesting..

Well the culprit in your code is the null value and way you are using it to assign the value to ContentDocumentLink.contentDocumentId.
You should query the content version object again to get the contentDocumentId (which is generated after the parent document is inserted by default because of you passing of null value).
Something like below :
ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = [SELECT Id, ContentDocumentId FROM ContentVersion WHERE Id =: cv.Id].ContentDocumentId;
cdl.LinkedEntityId = '00590000000a6dP';
cdl.ShareType = 'V';
insert cdl;

As per the salesforce documentation lines higlighted by you, "To create a document, create a new version via the ContentVersion object without setting the ContentDocumentId. This automatically creates a parent document record." it does create the parent document record as expected, but the contentDocumentId is still null in above initialised object. Id doesn't get updated automatically to the object instance. Infact you will have to pull out the corresponding Id as done in the above snippet.

Let me know if this helps.
This was selected as the best answer
Matthew HofmannMatthew Hofmann
That worked. Thank you!

I still wonder why I wasn't able to access the cv.ContentDucmentId after insert cv; perhaps the automatic creation of the ContentDocument record happens asyncronously, in which case the SOQL query assignment you described may also fail sometimes. I should handle that possiblity in a try catch block.

Thanks again!
VineetKumarVineetKumar
No, the creation of ContentDocument record is not done asyncronously.
To explain the behaviour, take it this way. Since salesforce follows an MVC framework(Model = Object, View = VF pages, Controller = Apex Classes).
In your class i.e., the controller, send the request to the Model(database) to create ContentVersion record, the record gets created and an Id is generated and associated to it. ThisId creation and association is done at the Model (database) level only. Your Controller doesn't know what this Id is, so to get this Id we again make a query to the Model(database) level to extract it and use it.

I'm not sure if this made things more clear or confused you more.. :)
Nader Hadji GhanbariNader Hadji Ghanbari
Would have been great if the API returned the id of the automatically created ContentDocuemnt. In Apex it's kinda fine but for REST API it forces us to send an extra request to infer the ContentDocuemnt Id.
Ravi Kumar 975Ravi Kumar 975
The pos was very helpful to me. I appreciate your effort. By the you can wish your friend on New Year Occassion (https://hindi-biography.com/happy-new-year-wishes-quotes/) and also you watch free movie at Moviezwap (https://bloggingfirst.com/moviezwap-telugu-movie/). Thanks 
shiv singh 31shiv singh 31
this very help full guide for me i like your hard work i have create some informating stuffs for you and all your occasssion happy birthday images (https://www.webshayari.in/search/label/HAPPY%20BIRTHDAY%20IMAGES?&max-results=7) . i think you like my hard work thanks 
my indiamy india
So finally we got something for indian game like myindiagame (http://myindiagame.com/)
Apk WepApk Wep
VideoBuddy App Download VideoBuddy App is a Powerful Application for Android to Download Videos from YouTube, Facebook, Twitter, etc and Earning App Various other Sites. Download VideoBuddy Android, Download VideoBuddy apk, VideoBuddy Download,VideoBuddy App Video Players & Tv Showes & Earning Apps.
VideoBuddy App Se Paise Kaise Kamaye
Apk WepApk Wep
<a href="https://www.apkwep.com/vclip-whatsapp-status-royal-pass-pbg/"><strong>VideoBuddy App</strong></a> Download <a href="https://www.apkwep.com/videobuddy-app/"><strong>VideoBuddy App</strong></a> is a Powerful Application for Android to <strong>Download Videos</strong> from <strong>YouTube</strong>, <strong>Facebook</strong>, <strong>Twitter</strong>, etc and <a href="http://dl.videoohot.com/su/CsRXPhAT"><strong>Earning App</strong></a> Various other Sites. <em>Download <strong>VideoBuddy</strong> Android, Download <a href="https://www.apkwep.com/videobuddy-app/"><strong>VideoBuddy apk</strong></a>, <strong>VideoBuddy</strong> Download,<strong><a href="https://www.apkwep.com/videobuddy-app/">VideoBuddy App </a>Video Players</strong> &amp; <strong>Tv Showes</strong> &amp; <a href="http://dl.videoohot.com/su/CsRXPhAT"><strong>Earning Apps</strong></a>.</em>

<a href="https://www.youtube.com/watch?v=DYhcnxqSx8g"><strong>VideoBuddy App Se Paise Kaise Kamaye</strong></a>
Apk WepApk Wep
VideoBuddy App Download VideoBuddy App is a Powerful Application for Android to Download Videos from YouTube, Facebook, Twitter, etc and Earning App Various other Sites. Download VideoBuddy Android, Download VideoBuddy ApkVideoBuddy Download,VideoBuddy App Video Players & Tv Showes & Earning Apps.
VideoBuddy App Se Paise Kaise Kamaye
Mayank ShauMayank Shau
Best website , i really love this hindi messages (https://www.hindimessages.in" target="_blank)
Apkmodszone besApkmodszone bes
best video editor apkmodszone.com/power-director-pro-apk (https://apkmodszone.com/power-director-pro-apk/)
Apk LegitApk Legit
manish moremanish more
I have found very good website on internet get latest songs lyrics free (https://www.songslyricsfree.com). 
manish moremanish more

I have visited this website once and read this article several times. this article is very helpful. Thank you for such information. ALso read this article 
best laptops under 50000 (https://www.techstudy.in/best-laptops-under-50000/)
Sadhana DeviSadhana Devi
Really this is a very informative article for me. thanks for share with me this information. you can enjoy Republic day Quotes in Hindi (https://ajabgajabjankari.com/army-day-quotes-in-hindi/" target="_blank) and if you an adult person so must read fidget toys (https://fidgettoysspinner.com/) and enjoy it. 
nguyen tam 4nguyen tam 4
try to this gambling website and it really works, thanks you: https://w88nhanh.com
Rohit Kumar 465Rohit Kumar 465
Nice information sir
Sad Status For WhatsApp in Hindi (https://www.statusforall.online/2020/03/sad-status-in-hindi.html?m=1)
 
kKyword BookmarkskKyword Bookmarks
These are really amazing and valuable websites you have shared with us. Thanks for the informative post..KeywordBookmarks.com    Visit For HD Display. (https://www.keywordbookmarks.com/2020/03/sd-movies-point-sd-movies-point-latest.html).
gemlocphat clubgemlocphat club
I tried it to our gambling website and it really works, thanks you: https://gem68.club (https://gem68.club/)
tai nguyen 11tai nguyen 11
Check if this betting site is working properly, thanks you:  w88city : https://w88city.club (https://w88city.club)
blog nha caiblog nha cai
Try visiting my website it works very well: https://blognhacai.com/
nin ninnin nin
My site provides information about football : https://keomacao.com
Paul EcherePaul Echere
Cool, thanks