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
Uri MaslovskyUri Maslovsky 

how can I fetch all files attached to a Case object.

Hi, I'd like to ask how can I fetch all files attached to a Case object. I'm using Lightning mode.

I don't seem to find where exactly ContentVersion, ContentDocument and ContentDocumentLink are somehow relates to Case object.

I'm looking for a way to locate and download all attachments based on a query where my input is Case number or case ID

Thanks in advance

VinayVinay (Salesforce Developers) 
Hi Uri,

Review below link which can explain on how to fetch attachments on case object.

Vinay Kumar
David Zhu 🔥David Zhu 🔥
With Lightning Experience, you may use the following code snippet to get the attachemnt.
List<ContentDocumentLink> contentDocumentLinks = [SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :caseId];   //pass caseId

        if (contentDocumentLinks .size() > 0)
            List<Id> contentDocumentLinkIds = new List<Id>();
            for (ContentDocumentLink contentDocumentLink : contentDocumentLinks )
                contentDocumentLinkIds .add(contentDocumentLink .ContentDocumentId);

            List<ContentVersion> contentVersions = [SELECT Id,ContentDocumentId,isLatest FROM ContentVersion WHERE ContentDocumentId in :contentDocumentLinkIds and FileType!='SNOTE' and IsLatest = true];

            if (contentVersions .size() > 0)
                List<Id> contentVersionIds= new List<Id>();

                for (ContentVersion contentVersion : contentVersions )
                    contentVersionIds.add(contentVersion .ContentDocumentId);
                List<ContentNote> contentNotes = [SELECT Id,Title,Content,TextPreview,CreatedDate,LastModifiedDate,,CreatedBy.Id,LastModifiedBy.Name FROM ContentNote WHERE ID in :contentVersionIds ORDER BY LastModifiedDate DESC];
                 for (ContentNote contentNote : contentNotes )
                   //EncodingUtil.base64Decode(EncodingUtil.base64Encode(contentNote.Content)).toString();     //this get the attachment body


Uri MaslovskyUri Maslovsky
Hi David,

Thanks for you quick response.
Query in line 19 seem to be not completed. I don't see its "FROM" and "WHERE" part.
Please advise. 

Uri MaslovskyUri Maslovsky
Hi Vinay,

Thanks for your quick response.
You are referring to "Attachment" object, which is not relevant, AFAIK, to Lightning mode which I'm using.
Please advise if you have an approach for Lightning mode.

David Zhu 🔥David Zhu 🔥
You can get the full code click the icon below. The line is not wrapped automatically.
User-added image

for the specific line, it is as below:

 List<ContentNote> contentNotes = [SELECT Id,Title,Content,TextPreview,CreatedDate,LastModifiedDate,,
CreatedBy.Id,LastModifiedBy.Name FROM ContentNote 
WHERE ID in :contentVersionIds ORDER BY LastModifiedDate DESC];                
Uri MaslovskyUri Maslovsky
Hi David,

Thanks for your help.

I tried to perform a query of: SELECT ContentDocumentId FROM ContentDocumentLink WHERE LinkedEntityId = :caseId
But once I put a 'Case' object ID there, the system returns with an answer that there are no records that match.
I did notice that the above query workes only if I use ID of object of type 'ContentWorkspace' .

Does it makes any sense?

David Zhu 🔥David Zhu 🔥
If you run the query in developer console, chances are you get nothing if the attachment is done by other users. You can add "Query All Files" permission to your profile or through permission set.

But if you run the code I provided through controller, it should return the expected result without "Query All Files" permission.
Uri MaslovskyUri Maslovsky
actually, I'm just taking the queries from your code and not running it as it is - since I'm connecting to SalesForce DB by means of PHP.
And while connecting to DB, I'm using a user with high enough permissions. and even though, I get nothing in return from first query, which is the exact query you advised, and it is also the one that start all process based on a given Case object.

Any other suggestions?

Thanks in advance
David Zhu 🔥David Zhu 🔥
Then you need to add a permission set to enable "Query All Files" permission and assign the permisison set to the user.
Uri MaslovskyUri Maslovsky

I added the needed permission to my account.
I now see that the third query doesn't return any records. I noticed that it is looking in an object called ContentNote. Why is specifically this object is needed to get all attached files?
isn't it suppose to be contentVertion object that holds the data? 
could you please explain what is the porpuse of the third query?

David Zhu 🔥David Zhu 🔥
You are right, it is not neccessary to do the last query. I copied my code from another project but it is not totally fit your requirement.
Here is the updated code.
List<ContentDocumentLink> contentDocumentLinks = [SELECT ContentDocumentId FROM 
                                                  ContentDocumentLink WHERE LinkedEntityId = :caseId];   //pass caseId

        if (contentDocumentLinks.size() > 0)
            List<Id> contentDocumentLinkIds = new List<Id>();
            for (ContentDocumentLink contentDocumentLink : contentDocumentLinks )
                contentDocumentLinkIds .add(contentDocumentLink .ContentDocumentId);

            List<ContentVersion> contentVersions = [SELECT Id,ContentDocumentId,Title,VersionData,isLatest FROM ContentVersion WHERE ContentDocumentId in :contentDocumentLinkIds and FileType!='SNOTE' and IsLatest = true];

            if (contentVersions.size() > 0)
                for (ContentVersion contentVersion : contentVersions )
                   //EncodingUtil.base64Decode(EncodingUtil.base64Encode(contentVersion .VersionData)).toString();     //this get the attachment body


Uri MaslovskyUri Maslovsky
I made a progress thanks to you!

Now I can reach some attachments objects which are attached to a given Case.
But, once I entered via browser to inspect the Case object, I noticed that I can see only 3 ContentDocumentId objects (meaning 3 attachments) while actually I can see many more files attached to this Case while inspecting it from attachments tab from browser (and not by performing SOQL queries via PHP)

the thing is that the user I'm using while performing PHP SOQL to SalesForce DB has much more privileges than those I have with my own user which I use to inspect Case manually object via browser - thus I concluded that it is not a permissions issue but something else.

Any idea?

Thanks in advance.
Uri MaslovskyUri Maslovsky
another thing I noticed...
Among the files I do see, they are .txt files, all other files which I don't see from SOQL query output are .jpg

does it makes any sense?
David Zhu 🔥David Zhu 🔥
1. Is it possible those missing attachments were attached in classic? File attached from Classic use different object even though your are using lighting now.

You can test this by using the following soql:

Select ID,Body,ContentType,Name from Attachment where parentId = :caseId

2. regarding .txt file issue,
You can add a field in line 10 query to get the file extension. It should contain all types of the extension.
List<ContentVersion> contentVersions = [SELECT Id,ContentDocumentId,Title,FileExtension,VersionData,isLatest FROM ContentVersion WHERE ContentDocumentId in :contentDocumentLinkIds and FileType!='SNOTE' and IsLatest = true];

José Ureña 1José Ureña 1
I found that when Email2Case is enabled, email attached pictures will show on the Case Files section, but if you try to query the ContentDocumentLink on the caseId you wont find the files.

On this case, you need to get all EmailMessages related to that Case, to then query the ContentDocumentLink based on related email ids.