[SalesForce] Move a ContentDocument from one library to another in Apex

Is there a direct way to do this in Apex?
I tried doing DML to ContentDocumentLink or ContentWorkspaceDoc. But nothing works.

What I tried so far

  1. Update the Library in ContentWorkspaceDoc
ContentWorkspaceDoc cv = new ContentWorkspaceDoc(
    Id = 'xxxxxxxxxxxxxxx', 
    ContentWorkspaceId = '{libraryId}');

update cv;

This gives me an error Document with ID: zzzzzzzzzzzzzzz already has an owning Library: [ContentDocumentId]

  1. Create new ContentDocumentLink and delete the old one
ContentDocumentLink dl = new ContentDocumentLink(
    LinkedEntityId = '{libraryId}',
    ContentDocumentId = 'zzzzzzzzzzzzzzz',
    ShareType = 'I'
);
insert dl;

delete new ContentDocumentLink(Id = '{old CDL Id}');

The creation works fine but removing the old link throws an error – DEPENDENCY_EXISTS, Cannot complete this operation. You cannot remove a document from its owning library. : : []

UPDATE:

We end up putting a link in our VF page to point to the standard Content detail page so user can Move a single content manually. Looks like this can't be done in bulk.

Best Answer

ContentWorkspace represents a content library. This object is available in versions 17.0 and later.

You need to Query the library where file needs to move and Create a new ContentDocumentLink record to associate your file to that library. Delete existing ContentDocumentLink which represents the file exist in older library.

You can refer this existing question on this for minimal required code:- How to Upload a File to a specific Library Folder using Apex?

Reference:- https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_objects_contentworkspace.htm

Update:-

ContentWorkspaceId is Read only. ID of the library document.

Instead of using ContentWorkspaceDoc, use ContentWorkspace which repersent Represents a content library. This object is available in versions 17.0 and later.

Query your library like this:-

ContentWorkspace ws = [SELECT Id, RootContentFolderId FROM ContentWorkspace WHERE Name = 'MyLibraryFolder' LIMIT 1];

relate the ContentDocument to queried Library like this:-

ContentDocumentLink cdl = new ContentDocumentLink();
cdl.ContentDocumentId = cv.ContentDocumentId;
cdl.ShareType = 'I';
cdl.Visibility = 'AllUsers';
cdl.LinkedEntityId = ws.Id;
insert cdl;