Deletes one or more S-Drive file records from Salesforce and from the storage bucket.
See https://cyangate.atlassian.net/wiki/x/BAA63g for an explanation deleteFiles vs deleteS3Files.
Ways to call this method
global static List<ResultObject> deleteFiles(List<Id> wipIds, String objectId)
public static List<ResultObject> deleteFiles(List<Id> wipIds, String objectId, Boolean isDeleteS3Object, List<String> versionIds)
Parameters
|
Parameter |
Type |
Required |
Description |
|---|---|---|---|
|
|
|
Yes |
IDs of the file record(s) to delete — e.g. |
|
|
|
Yes |
The ID of the parent record the file(s) are attached to (e.g. the Account, Case, Contact….) Accepts both 15- and 18-character Salesforce ID formats. |
|
|
|
No Defaults to true. Should be set to true if used (see additional explanation in Description column) |
True: Deletes the file from the bucket as well as deleting the record from Salesforce. There’s no reason to set this to false. 1
|
|
|
|
No |
Only relevant for version-enabled buckets. One version ID per entry in Passing version IDs for a bucket that isn't version-enabled will fail — omit this parameter entirely if you don't use versioning. You can only supply |
Return value
Returns List<ResultObject>, one entry per ID in wipIds, in the same order. Each ResultObject has:
|
Field |
Description |
|---|---|
|
|
|
|
|
Populated when |
Always check status per record — a partial failure (e.g. 2 of 5 files deleted) does not throw an exception, it just reports 'fail' for the ones that didn't succeed.
Check Results
Check every ResultObject.status in the response — don't assume success just because no exception was thrown.
➡️ Calling this more than once in the same transaction
With isDeleteS3Object = true (the default), a single call to deleteFiles does both a callout (deleting the object from S3/GCS) and a DML delete (removing the Salesforce record). That's fine on its own — but if you call deleteFiles more than once inside the same Apex transaction (for example, looping over several parent records and calling it once per parent), the second call will fail with a System.CalloutException: "You have uncommitted work pending. Please commit or rollback before calling out."
This isn't an S-Drive-specific error — it's a Salesforce platform rule: once any DML has happened in a transaction, you can't make a callout afterward without committing first. The first call's DML (deleting its Salesforce record) is still uncommitted by the time the second call tries to make its own callout, so the platform blocks it.
Symptom: if you don't handle this, it tends to look like only the first group of files got deleted and the rest were silently skipped — especially if the exception is caught somewhere outer and only logged (e.g. System.debug) rather than surfaced, which makes the partial failure easy to miss entirely.
What to do instead: don't loop over multiple deleteFiles calls synchronously in one transaction. Options include:
-
Chaining a separate asynchronous unit of work (e.g. a
Queueable) per group, so each call gets its own transaction. -
Restructuring so each transaction only ever calls
deleteFilesonce.
If you do end up calling it in a loop anyway, at minimum wrap each individual call in its own try/catch — not one try/catch around the whole loop — and record every failure (not just debug-log it), so a failure on one group doesn't silently swallow every group after it.
Examples
Delete files and their stored content (default behavior)
List<Id> fileIdsToDelete = new List<Id>{ '069XX0000004Cx1AAE', '069XX0000004Cx2AAE' };
String parentAccountId = '001XX000003DHPh';
List<ResultObject> results = SDriveTools.deleteFiles(fileIdsToDelete, parentAccountId);
for (ResultObject r : results) {
if (r.status == 'fail') {
System.debug(LoggingLevel.ERROR, 'Failed to delete a file: ' + r.errorMessage);
}
}
Delete one specific old version, keeping the rest of the version history
// fileIds should reference the file record whose version history you're pruning
List<Id> fileIds = new List<Id>{ 'a00XX0000004Cx1AAE' };
List<String> versionIdsToDelete = new List<String>{ 'gYpM6i4tKX8DcHel...' }; // an old S3/GCS version ID
List<ResultObject> results = SDriveTools.deleteFiles(
fileIds,
'001XX000003DHPh',
true, // delete from storage
versionIdsToDelete // ...but only this specific version
);
1 If you only want to remove the Salesforce record (not the stored file)
Use standard DML instead.
List<Id> fileIdsToDelete = new List<Id>{ 'a00XX0000004Cx1AAE' };
delete [SELECT Id FROM cg__AccountFile__c WHERE Id IN :fileIdsToDelete];
This removes the Salesforce record(s) and leaves the file untouched in the bucket.