Google Apps Script to backup Docs from Google Drive

This script for Google Drive finds all Google Doc-files inside Drive, converts them to PDF and sends them via (one or more) emails to the currently logged in user. Since there’s a quota of 25 MB for attachments in one email the script sends multiple emails if the PDFs get too large.

As a backup it’s useful to have a copy of the Doc files because they exist only as links on your local Drive folder, so in case you accidentally delete them (or something goes wrong at Google, which is not very probable) you at least have a read-only copy.

The script is used as a web-app, so it can be triggered via a URL.

Important

Please note (“Disclaimer”): Knowledge of Google Apps Script is required. For me it works – but it wasn’t extensively testet. Therefore: This script is provided ‘as is’, it might delete all your data or cause other problems. You can use this script freely, but do not redistribute it.

If you have too many Google Docs (with about 20 medium sized docs it worked), the script may take too long and stop with a timeout – in this case the script below is not the right solution.

The script backups not only your Google Docs but all Docs in your account – so if you once opened a Google Doc via a link from somebody else this is also included.

Prevent sending files shared with the current user

If you want to receive only files created by you, not files shared with you, change this line in cwBackupDocs.gs…

if (file.isTrashed() /* || file.getOwner().getEmail() != Session.getActiveUser().getEmail() */) {

…to…

if (file.isTrashed() || file.getOwner().getEmail() != Session.getActiveUser().getEmail() ) {

Files

The apps script consists of the following three files, all in the same folder. If you publish it as web-app in your account you get the URL with which to call the backup process, please note that it might take some minutes.

cwBackupDocs.gs

/**
 * CwBackupDocs
 * v1
 *
 * - Backup all Google Docs files in Google Drive
 * - Docs are converted to pdf and sent via e-mail(s) to the current user
 *
 * @author Mario Fischer <mario@chipwreck.de>
 */

/**
 * Backup method: Collect google docs, convert to PDF and send via one or more emails according to filesize
 * 
 * @return string
 */
function cwBackupDocs() 
{  
  var maxQuota = 26214400; // 25MB is the quota for attachments
  maxQuota = maxQuota / 3; // Since exact calculation is difficult (attachment encoding etc.),
                           // we sent an email as soon as attachment size exceeds ~8MB
  
  // Find all google doc files 
  var files = DriveApp.getFilesByType(MimeType.GOOGLE_DOCS);
  
  var body = "";
  var attachments = [];
  var size = 0;
  var mailsSent = 0;
   
  // Convert documents to PDF and collect attachments
  // Send an email as soon as we exceed our quota
  
  while (files.hasNext()) {
    
    var file = files.next();

    if (file.isTrashed() /* || file.getOwner().getEmail() != Session.getActiveUser().getEmail() */) {
      continue; // do not backup trashed files
    }
    var doc = DocumentApp.openByUrl(file.getUrl());
    var pdf = doc.getAs(MimeType.PDF);
    size += pdf.getDataAsString().length;
    
    if (size >= maxQuota) {
      // We're above the quota, send an email now and reset variables
      
      sendDocs(body, attachments);
      mailsSent++;
      
      attachments = [];
      body = "";
      size = 0;
      
      continue;
    } 
    
    body += 'Document: ' + doc.getName() + "\nLink: " + doc.getUrl() + "\n\n";    
    attachments.push(pdf);
  }
  
  sendDocs(body, attachments);

  return ++mailsSent + " mails sent.";
}

/**
 * Send an email to the logged-in user with given body text and attachments
 * 
 * @param body string
 * @param attachments BlobSource[]
 */
function sendDocs(body, attachments)
{
  var email = Session.getActiveUser().getEmail();
  var subject = 'Backup from Google Docs - ' + Utilities.formatDate(new Date(), "GMT", "yyyy-MM-dd");
  var body = "Backups are attached.\n\n" + body + "\n--\nRegards.\n";
  
  GmailApp.sendEmail(email, subject, body,  {
    'attachments': attachments
  });
}

/**
 * GET for web service call
 *
 * @param e string
 * @return HTMLOutput
 */
function doGet(e)
{
  var params = JSON.stringify(e);
  return HtmlService.createTemplateFromFile('index').evaluate();
}

/**
 * includer-helper
 *
 * @param filename string
 * @return string
 */
function include(filename)
{
  return HtmlService.createHtmlOutputFromFile(filename)
      .getContent();
}

index.html

<!DOCTYPE html>
<html>
  <head>
  <base target="_top">
  <?!= include('javascripts'); ?>
  </head>
    
  <body>
    <h2>CwBackup Docs</h2>
    <p>Please wait… (creating emails now, this can take several minutes.)</p>
    
    <div id="output"></div>
  </body>
</html>

javascripts.html

<script>
// cwBackupDocs - www.chipwreck.de
window.addEventListener('load', function() {
  
  function onFailure(error) {
        alert(error);
        var div = document.getElementById('output');
        div.innerHTML = "ERROR: " + error.message;
  }
  
  function onSuccess(result) {
        var div = document.getElementById('output');
        div.innerHTML = 'Success: ' + result;
  }

  google.script.run.withFailureHandler(onFailure).withSuccessHandler(onSuccess)
          .cwBackupDocs();
});
</script>

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.