S-Drive 3.6 Documentation

completeUpload()

The mandatory final step of any upload — whether you used a single direct upload or the multipart flow. Marks the file record's upload as finished (clears its "Work In Progress" state) so it shows up as a normal, finished file.

Call this only after the file's bytes have actually finished uploading to storage. Calling it early marks an empty or partial file as "done" — anyone who downloads it afterward will see corrupted or missing content, with no warning that anything went wrong.

How to call this method

global static List<ResultObject> completeUpload(List<Id> wipIds)

global static List<ResultObject> completeUpload(List<Id> wipIds, List<String> versionIdList)

Parameters

Parameter

Type

Required

Description

wipIds

List<Id>

Yes

The WIP file record Id(s) to finalize — the wipFileId values from initializeUpload's UploadRequestInfo.

versionIdList

List<String>

No

Only for version-enabled buckets — one storage version Id per entry in wipIds, in the same order, recording which version this upload created. Where this value comes from: it's not something SDriveTools generates for you — when your code uploads the file's bytes to S3, S3's response includes an x-amz-version-id header (for a version-enabled bucket); read that header off the upload response and pass it in here. (GCS-backed orgs use a different mechanism, not covered on this page.) Omit this parameter entirely for non-versioned buckets.

Return value

Returns List<ResultObject>, one per Id in wipIds, in the same order:

Field

Description

status

'success' or 'fail'

errorMessage

Populated when status == 'fail' — see the table below for the list of messages.


What errorMessage can say

Message

Cause

Fix

"Wip Id is null"

One of the entries in wipIds is null.

Don't pass null Ids — filter them out first.

"No such wip file with provided id"

An Id in wipIds doesn't match any WIP file record.

Double-check you're passing the wipFileId values initializeUpload actually returned.

"There is no wip file(s)"

Every entry in wipIds was null, or the list was empty.

Pass at least one non-null Id.

"Insufficient Privileges. You do not have access to update operation."

The running user doesn't have update access to the file object.

Grant update permission on the object, or run as a user who has it.

Error code 417 — "It is not allowed to upload a new version on the not version-enabled bucket"

You passed a versionIdList entry for a file whose bucket isn't version-enabled.

Omit versionIdList for non-versioned buckets.

A partial failure (some files finalized, others not) does not throw an exception — check every status.

What this also does

  • If this org has previews/thumbnails enabled for the object and file type, completing the upload also kicks off preview/thumbnail generation for the file.

  • If this was a new-version upload, the previous version's "is latest version" flag is cleared automatically.

⚠ Before you call this

  • Don't call this before the storage upload has actually finished. Nothing stops you from calling it early — it will happily mark an unfinished file as complete.

  • This is required after both upload paths: the simple direct-upload path, and right after completeMultiPartUpload on the large-file path. It's easy to forget the second case when you're calling storage directly from client-side code, since at that point you may never come back to Salesforce in the same flow.

Example

List<ResultObject> results = SDriveTools.completeUpload(new List<Id>{ info.wipFileId });

for (ResultObject r : results) {
    if (r.status == 'fail') {
        System.debug(LoggingLevel.ERROR, 'Failed to finalize upload: ' + r.errorMessage);
    }
}

With a version-enabled bucket

Read x-amz-version-id off the response from uploading the file's bytes, and pass it through:

// res is the HttpResponse from uploading info's bytes to storage (see
// "Uploading a file end-to-end" for that step)
String versionId = res.getHeader('x-amz-version-id');

List<ResultObject> results = SDriveTools.completeUpload(
    new List<Id>{ info.wipFileId },
    new List<String>{ versionId }
);

Verifying the upload succeeded

Neither completeUpload nor the upload step itself automatically confirms the bytes arrived intact — that's on you to check, if you want the extra assurance. Two options, both optional:

  • Compute the file's MD5 checksum yourself before uploading, then compare it against the ETag header S3 returns — either from the upload response directly (if you set success_action_status: '201' when uploading, S3's response body is XML containing the ETag), or by calling getAmazonHeaders afterward and reading ETag from the returned headers.

  • If they match, the upload arrived byte-for-byte as sent.