Skip to content

Added support for uploading new file versions, revisions and labels, full shared drive and permission management, scoped access tokens, and download links for large files

Latest

Choose a tag to compare

@sandriiy sandriiy released this 30 Aug 18:09
50edf71

🎉 What's New in This Release

  • New Features

    • Upload a new version of an existing file

      A file can now be updated with new content while keeping the same file ID, the same sharing and the same links. Every upload adds an entry to the file's version history, so changes stay auditable instead of being lost to a delete-and-recreate.

      The three existing upload builders are reused, so only the entry point changes: simpleUpdate(), multipartUpdate() and resumableUpdate() mirror the existing simpleCreate(), multipartCreate() and resumableCreate().

      GoogleDrive remoteGoogleDrive = new GoogleClientApiProvider().retrieveGoogleDriveClient();
      
      GoogleFileEntity newVersion = remoteGoogleDrive.files().modify().simpleUpdate(remoteFileId)
          .setContentType('text/plain')
          .setBody(Blob.valueOf('The new content of the file'))
          .setKeepRevisionForever(true)
          .setSupportsAllDrives(true)
          .execute();

      In this example:

      • remoteFileId is the Google Drive file whose content is being replaced.
      • setKeepRevisionForever(true) pins the revision so Google Drive does not purge it 30 days after newer content is uploaded.
      • setSupportsAllDrives(true) ensures the request works for both My Drive and Shared drives.

      Note that setParentFolders(...) must not be used on an update, as Google Drive rejects parents in an update body. Use addParentFolders(...) and removeParentFolders(...) to move a file instead.

    • New revisions() category

      The version history of a file is now readable and manageable through search(), retrieve(), modify() and remove(). The Google Drive API has no revert endpoint, so restoring an earlier version is done by reading that revision's content and uploading it back as a new version.

      GoogleRevisionEntity previous = remoteGoogleDrive.revisions().retrieve(remoteFileId, revisionId)
          .setRevisionDownloadType(GoogleRetrieveRevisionBuilder.DownloadType.CONTENT)
          .execute();
      
      GoogleFileEntity restored = remoteGoogleDrive.files().modify().simpleUpdate(remoteFileId)
          .setContentType('text/plain')
          .setBody(previous.bodyAsBlob)
          .execute();
    • New labels() category

      Labels applied to a file can now be listed and changed through search() and modify(). A label is attached and its fields are populated in a single request, and every Google Drive field type is supported: text, selection, date, integer and user.

    • Full shared drive management

      The drives() category now covers the whole lifecycle rather than search alone: create(), retrieve(), modify(), remove(), hide() and unhide().

    • Retrieve and update permissions

      The permissions() category gains retrieve() and modify(), so an existing permission can be read and changed: promoting a reader to a writer, setting an expiry, or transferring ownership.

    • Download links for large files

      files().retrieve().downloadLink() asks Google Drive for a download URL instead of the bytes. The link is passed to the browser or a Lightning Component, so the content never enters the Apex heap and file size stops being a Salesforce concern. The long-running operation behind it is read back with the new operations().retrieve().

      GoogleOperationEntity operation = remoteGoogleDrive.files().retrieve().downloadLink(remoteFileId)
          .execute();
      
      String linkForTheBrowser = operation.response.downloadUri;
    • Scoped access tokens

      The GoogleAuthorizer interface asks your class for a token without telling it what the token is for, which is why most implementations end up requesting the full drive scope for everything. Scopes can now be declared up front, and an authorizer implementing the new GoogleScopedAuthorizer interface receives them.

      GoogleCredential credential = new GoogleAuthorizationCodeFlow.Builder()
          .setLocalGoogleAuthorizer('CustomScopedAuthorizer')
          .setRequestedScopes(new List<GoogleScope>{ GoogleScope.DRIVE_FILE })
          .build();

      The declared scopes also take part in the Platform Cache key, so a token cached for one set of scopes is never handed to an operation that asked for another. An authorizer implementing only GoogleAuthorizer keeps working exactly as before.

  • Developer Experience / Reliability

    • setDriveId(...) now sends the corpora=drive value Google Drive requires alongside it
    • Content-Length is no longer set manually on PATCH callouts, which Salesforce rejects
    • Improved test coverage

📖 Documentation

To access the documentation, please refer to the GitHub Wiki:

🛠️ Installation


sf package install --wait 20 --security-type AdminsOnly --package 04tQy000000ZFIjIAO
sfdx force:package:install --wait 20 --securitytype AdminsOnly --package 04tQy000000ZFIjIAO