Context
We have an app that extends Salesforce Content functionality that creates a custom collaboration and approval process experience.
In the app we've developed a custom component that utilizes the ConnectApi.ContentHub methods to allow users to search for content in their Google Drive accounts and create content versions (this mimics the standard file explorer from salesforce, but they do not have a standard component to host this where we need it / we need customizations to it for our usecase)
This is done by getting the file details from the external data source and creating a ContentVersion
Using ContentHub to create a ContentVersion
List<CM_FilesConnectItem> driveItems = new List<CM_FilesConnectItem>();
ConnectApi.RepositoryFolderItemsCollection itemCollection = ConnectApi.ContentHub.getRepositoryFolderItems(
this.repository.Id,
this.folderId,
pageParam,
null
);
for (ConnectApi.ContentHubItem item : itemCollection.items) {
CM_FilesConnectItem driveItem = new CM_FilesConnectItem();
driveItem.id = item.file.id;
driveItem.name = item.file.name;
driveItem.title = item.file.title;
driveItem.description = item.file.description;
driveItem.isFolder = false;
driveItem.mimeType = item.file.mimeType;
driveItem.externalUrl = item.file.externalDocumentUrl;
driveItems.add(driveItem);
}
return driveItems;
// After the user selects which file
ContentVersion cv = new ContentVersion(
Title = driveItem.title,
PathOnClient = driveItem.title + extensionFromMimeType(driveItem.mimeType),
ContentLocation = 'E',
origin = 'H',
ExternalDocumentInfo1 = driveItem.externalUrl,
ExternalDocumentInfo2 = driveItem.id,
ExternalDataSourceId = this.repository.Id
);
insert cv;
In our app, when users are done collaborating we'd like to "snapshot" the final changes and physically bring in the file contents.
The ConnectApi.ContentHub.getRepositoryFile
is supposed to return the ContentBody as a string, but we've found this unreliable for various content types e.g. word, powerpoint, etc - and returns null
for these file types.
We've resulted to calling the Salesforce API to grab the file contents for us and creating a new ContentVersion
"Copy" file contents to a content version
public ContentVersion createLocalContentVersionFromExternal(Id externalCVId) {
ContentVersion externalCV = (ContentVersion) CM_ContentVersionSelector.newInstance().selectById(externalCVId);
String endpoint =
System.URL.getOrgDomainURL().toExternalForm() +
'/services/data/v' +
String.valueOf(CM_Constants.CM_SFDC_API_VERSION) +
'/connect/files/' +
externalCV.ContentDocumentId +
'/content';
Http http = new Http();
HttpRequest request = new HttpRequest();
request.setEndpoint(endpoint);
request.setMethod('GET');
(uses VF page session id since UserInfo.getSessionId will have lightning session id limited access)
request.setHeader('Authorization', 'OAuth ' + SessionID.getSessionID());
HttpResponse response = http.send(request);
String fileName = getFileNameFromContentDisposition(response.getHeader('Content-Disposition'));
ContentVersion snapshotVersion = new ContentVersion(
Title = externalCV.Title,
VersionData = response.getBodyAsBlob(),
PathOnClient = fileName,
ContentLocation = 'S',
Origin = 'H'
);
insert snapshotVersion;
return snapshotVersion;
}
The problem
The problem with this approach is that we are pulling the content body into memory, which will impose the 6MB heap limit(12MB if asynchronous) on the files that we can support which is far less than the 2GB Salesforce natively supports for file sizes.
We are aware that standard files connect has the ability to either "copy" the file contents or "reference" them, but to our knowledge they don't provide a ConnectApi.ContentHub
method to support copying the file without needing to "touch" the blob data.
Additionally our requirements require us to use a hybrid approach of both "reference" and "copy" so we keep the setting to "reference" to support the collaboration requirement.
Are there any Salesforce supported methods to "copy" the file that we are overlooking before we consider creating an external service that doesn't have the 6MB limit to handle the snapshotting?