Save Documents to Google Drive in TypeScript DOCX Editor

28 Aug 202610 minutes to read

To save a document to Google Drive, you can follow the steps below.

Step 1: Set up the Google Drive API

You must set up a project in the Google Developers Console and enable the Google Drive API. Obtain the necessary credentials to access the API. For more information, see the official link.

Step 2: Create a simple DOCX Editor sample in TypeScript

Follow the instructions provided in this link to create a simple DOCX Editor sample in TypeScript. This will give you a basic setup of the DOCX Editor component.

Step 3: Modify the DocumentEditorController.cs file in the web service project

  • Create a web service project in .NET Core 3.0 or above. You can refer to this link for instructions on how to create a web service project.

  • Open the DocumentEditorController.cs file in your web service project.

  • Import the required namespaces at the top of the file:

using System.IO;
using Google.Apis.Drive.v3;
using Google.Apis.Util.Store;
  • Add the following private fields and constructor parameters to the DocumentEditorController class. In the constructor, assign the values from the configuration to the corresponding fields.
private IConfiguration _configuration;
public readonly string folderId;
public readonly string applicationName;
public readonly string credentialPath;
private static readonly string[] Scopes = { DriveService.Scope.DriveFile, DriveService.Scope.DriveReadonly };

public DocumentEditorController(IWebHostEnvironment hostingEnvironment, IMemoryCache cache, IConfiguration configuration)
{
  _hostingEnvironment = hostingEnvironment;
  _cache = cache;
  _configuration = configuration;
  folderId = _configuration.GetValue<string>("FolderId");
  credentialPath = _configuration.GetValue<string>("CredentialPath");
  applicationName = _configuration.GetValue<string>("ApplicationName");
}
  • Create the SaveToGoogleDrive() method to save the downloaded document to Google Drive.
[AcceptVerbs("Post")]
[HttpPost]
[EnableCors("AllowAllOrigins")]
[Route("SaveToGoogleDrive")]
//Post action for downloading the document

public async void SaveToGoogleDrive(IFormCollection data)
{
   if (data.Files.Count == 0)
    return;

  IFormFile file = data.Files[0];
  string documentName = this.GetValue(data, "documentName");
  string result = Path.GetFileNameWithoutExtension(documentName);
  string fileName = result + "_downloaded.docx";
          
  UserCredential credential;

  using (var fileStream = new FileStream(credentialPath, FileMode.Open, FileAccess.Read))
  {
    string credPath = "token.json";
    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
    GoogleClientSecrets.Load(fileStream).Secrets,
    Scopes,
    "user",
     CancellationToken.None,
    new FileDataStore(credPath, true));
  }
          
  // Create the Drive API service.
  var service = new DriveService(new BaseClientService.Initializer()
  {
    HttpClientInitializer = credential,
    ApplicationName = applicationName,
  });

  var fileMetadata = new Google.Apis.Drive.v3.Data.File()
  {
    Name = fileName,
    Parents = new List<string> { folderId }
  };

  Stream stream = new MemoryStream();
  file.CopyTo(stream);

  FilesResource.CreateMediaUpload request = service.Files.Create(fileMetadata, stream, "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
  request.Fields = "id";
  await request.UploadAsync();
}

private string GetValue(IFormCollection data, string key)
{
    if (data.ContainsKey(key))
    {
        string[] values = data[key];
        if (values.Length > 0)
        {
            return values[0];
        }
    }
    return "";
}
  • Open the appsettings.json file in your web service project. Add the following lines below the existing "AllowedHosts" configuration.
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "FolderId": "Your Google Drive Folder ID",
  "CredentialPath": "Your Path to the OAuth 2.0 Client IDs JSON file",
  "ApplicationName": "Your Application Name"
}

  1. Replace Your Google Drive Folder ID, Your Application Name, and Your Path to the OAuth 2.0 Client IDs JSON file with your actual Google Drive folder ID, your name for your application, and the path for the JSON file.
  2. The FolderId part is the unique identifier for the folder. For example, if your folder URL is: https://drive.google.com/drive/folders/abc123xyz456, then the folder ID is abc123xyz456.
  3. You must use a unique Client_ID from the JSON file to interface your application with the Google Drive API in order to save the document directly to Google Drive. This Client_ID will serve as the authentication key, allowing you to save files securely.

Step 4: Modify the index file in the DOCX Editor sample

On the client side, export the document as a blob using saveAsBlob and send it to the server side for saving to Google Drive.

import { DocumentEditorContainer, Toolbar } from '@syncfusion/ej2-documenteditor';

// Inject require modules.
DocumentEditorContainer.Inject(Toolbar);

//Initialize Document Editor component
let documentEditorContainer: DocumentEditorContainer = new DocumentEditorContainer({ enableToolbar: true, height: '590px', serviceUrl: 'http://localhost:62870/api/documenteditor/' });

// Render Document Editor component.
documentEditorContainer.appendTo('#DocumentEditor');

document.getElementById('export').addEventListener('click', (): void => {
    save();
});

async function save(): Promise<void> {
    documentEditorContainer.documentEditor.saveAsBlob('Docx').then((blob: Blob) => {
        let exportedDocument = blob;
        //Now, save the document where ever you want.
        let formData: FormData = new FormData();
        formData.append('documentName', documentEditorContainer.documentEditor.documentName);
        formData.append('data', exportedDocument);
        /* tslint:disable */
        let req = new XMLHttpRequest();
        // Replace your running Url here
        req.open(
            'POST',
            'http://localhost:62870/api/documenteditor/SaveToGoogleDrive',
            true
        );
        req.onreadystatechange = () => {
            if (req.readyState === 4) {
                if (req.status === 200 || req.status === 304) {
                    console.log('Saved sucessfully');
                }
            }
        };
        req.send(formData);
    });
}
<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 Animation</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="Typescript UI Controls" />
    <meta name="author" content="Syncfusion" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-documenteditor/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-buttons/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-base/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-dropdowns/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-inputs/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-lists/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-navigations/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-popups/styles/fabric.css" rel="stylesheet" />
    <link href="https://cdn.syncfusion.com/ej2/34.2.2/ej2-splitbuttons/styles/fabric.css" rel="stylesheet" /> 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>

<body>
    <div>
        <button id="export">Save to Google Drive</button>
    </div>
    <div id="DocumentEditor"></div>
</body>

</html>

The Google.Apis.Drive.v3 NuGet package must be installed in your application to use the preceding code example.