Saturday, November 9, 2019

Convert Attachment to File in Salesforce Using Apex

If you want to modify System audit Fields like CreatedDate, CreatedById, etc fields while converting to file. you must have the below permission "Set Audit Fields upon Record Creation" and "Update Records with Inactive Owners" 

How to Enable?

From Setup, enter User Interface in the Quick Find box, and then select "Set Audit Fields upon Record Creation" and "Update Records with Inactive Owners" 

Activating this feature in User Interface allows you to grant permission to set audit fields and update records with inactive owners, but it does not grant the permission by default.
You will need to grant the following profile permissions to your Users(Who are converting to file)

Set Audit Fields upon Record Creation - Allow the User to set audit fields (like 'Created By' or 'Last Modified By') when you create a record via API importing tools like Data Loader.
Update Records with Inactive Owners - Allow the User to update record owner and sharing-based records with inactive owners.

Add a permission set

1. Navigate to Setup.
2. Quick Find 'Permission Set'.
3. Click New.
4. Enter the name of the permission set.
5. Under System Permissions, grant any of the 2 permissions:
    i. Set Audit Fields upon Record Creation
    ii. Update Records with Inactive Owners
6. Click Save.
7. Click Manage Assignments.
8. Search for the name of the Users that will need the permission.
9. Click Add Assignment.

After you have permission now you are ready to convert the file.

Sample Code
list<ContentVersion> lstCntVersionsToInsert = new list<ContentVersion>();
list<Attachment> lstAttachments = [SELECT Id, ParentId, Name, IsPrivate, Body, OwnerId, CreatedById, CreatedDate, Description FROM Attachment where ParentId != null];
for(Attachment attIterator : lstAttachments) {
 ContentVersion objCntVersion = new ContentVersion();
 objCntVersion.Title = attIterator.Name;
 objCntVersion.PathOnClient = '/' + attIterator.Name;
 objCntVersion.VersionData = (attIterator.Body == null ? Blob.valueOf('.') : attIterator.Body);
 objCntVersion.Description = attIterator.Description;
 objCntVersion.SharingPrivacy = 'N'; // Can be always public.
 objCntVersion.FirstPublishLocationId = attIterator.ParentId; // Parent Id
 objCntVersion.OwnerId = attIterator.OwnerId;
 // To avoid "Documents in a user's private library must always be owned by that user" error.
 objCntVersion.CreatedById = attIterator.OwnerId; 
 objCntVersion.CreatedDate = attIterator.CreatedDate;
 objCntVersion.FirstPublishLocationId = attIterator.OwnerId;

if(!lstCntVersionsToInsert.isEmpty()) {
    insert lstCntVersionsToInsert;


  1. good,it's working well. thank you

  2. I tried using the code and got the required field missing error of ExternalDataSourceId(Lookup field) on content version.ExternalDataSource is an object in salesforce.I uploaded a attachment on portal and want to converted to file inorder to view that attachment as file for internal Salesforce Lightning users, so I wrote a trigger on attachment to convert attachment to file.

  3. Tried this way it works as file but the file's contents are showing nothing although the attachment body has content. Any thoughts why?