Save document to Google Drive

8 Jan 202414 minutes to read

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

Step 1: Set up 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, view the official link.

Step 2: Create a Simple Document Editor sample in JavaScript

Follow the instructions provided in this link to create a simple Document Editor sample in Javascript. This will give you a basic setup of the Document 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 bucket
[AcceptVerbs("Post")]
[HttpPost]
[EnableCors("AllowAllOrigins")]
[Route("SaveToGoogleDrive")]
//Post action for downloading the document

public 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 memStream = new FileStream(credentialPath, FileMode.Open, FileAccess.Read))
  {
    string credPath = "token.json";
    credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
    GoogleClientSecrets.Load(memStream).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;
  request = service.Files.Create(fileMetadata, stream, "application/pdf");
  request.Fields = "id";
  object value = 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"
}

NOTE

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.

NOTE

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.

NOTE

You must use a unique Client_ID from json file to interface your application with the Google Drive API in order to save 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 Document Editor sample

In the client-side, to export the document into blob the document using saveAsBlob and sent to server-side for saving in Google Drive.

<!DOCTYPE html>
<html lang="en">

<head>
    <title>EJ2 DocumentEditor</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">
    <!-- EJ2 Document Editor dependent theme -->
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-base/styles/material.css" rel="stylesheet" type="text/css"
        rel='nofollow' />
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-buttons/styles/material.css" rel="stylesheet" type="text/css"
        rel='nofollow' />
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-inputs/styles/material.css" rel="stylesheet" type="text/css"
        rel='nofollow' />
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-popups/styles/material.css" rel="stylesheet" type="text/css"
        rel='nofollow' />
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-lists/styles/material.css" rel="stylesheet" type="text/css"
        rel='nofollow' />
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-navigations/styles/material.css" rel="stylesheet"
        type="text/css" rel='nofollow' />
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-splitbuttons/styles/material.css" rel="stylesheet"
        type="text/css" rel='nofollow' />
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-dropdowns/styles/material.css" rel="stylesheet"
        type="text/css" rel='nofollow' />

    <!-- EJ2 Document Editor theme -->
    <link href="https://cdn.syncfusion.com/ej2/29.2.4/ej2-documenteditor/styles/material.css" rel="stylesheet"
        type="text/css" rel='nofollow' />

    <!-- EJ2 Document Editor dependent scripts -->
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-base/dist/global/ej2-base.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-data/dist/global/ej2-data.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-svg-base/dist/global/ej2-svg-base.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-file-utils/dist/global/ej2-file-utils.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-compression/dist/global/ej2-compression.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-pdf-export/dist/global/ej2-pdf-export.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-buttons/dist/global/ej2-buttons.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-popups/dist/global/ej2-popups.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-splitbuttons/dist/global/ej2-splitbuttons.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-inputs/dist/global/ej2-inputs.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-lists/dist/global/ej2-lists.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-navigations/dist/global/ej2-navigations.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-dropdowns/dist/global/ej2-dropdowns.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-calendars/dist/global/ej2-calendars.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-charts/dist/global/ej2-charts.min.js"
        type="text/javascript"></script>
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-office-chart/dist/global/ej2-office-chart.min.js"
        type="text/javascript"></script>
    <!-- EJ2 Document Editor script -->
    <script src="https://cdn.syncfusion.com/ej2/29.2.4/ej2-documenteditor/dist/global/ej2-documenteditor.min.js"
        type="text/javascript"></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' style='height:620px'></div>
    <script>
        // Initialize DocumentEditorContainer component.
        var documenteditorContainer = new ej.documenteditor.DocumentEditorContainer({ enableToolbar: true, height: '590px' });
        ej.documenteditor.DocumentEditorContainer.Inject(ej.documenteditor.Toolbar);
        documenteditorContainer.serviceUrl = 'http://localhost:62870/api/documenteditor/';
        //DocumentEditorContainer control rendering starts
        documenteditorContainer.appendTo('#DocumentEditor');
        document.getElementById('export').addEventListener('click', function () {
            save();
        });

        async function save() {
            container.documentEditor.saveAsBlob('Docx').then((blob) => {
                var exportedDocument = blob;
                //Now, save the document where ever you want.
                var formData = new FormData();
                formData.append('documentName', container.documentEditor.documentName);
                formData.append('data', exportedDocument);
                /* tslint:disable */
                var 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);
            });
        }
    </script>
</body>

</html>

NOTE

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