Search code examples
google-apps-scriptrtf

Manipulating RTF files with GAS (to gdoc, en masse)


Is there a way to programmatically convert RTF files to gdocs, or if you can't convert then just copy the contents? I have hundreds to store in gdrive so I'd prefer to convert them to make them easier to manipulate and merge later.


Solution

    • You want to convert RTF file to Google Document.
    • There are several hundreds of RTF files.

    If my understanding is correct, how about this sample script?

    As a simple conversion, you can use the script of Drive.Files.copy({mimeType: MimeType.GOOGLE_DOCS}, fileId) using Advanced Google Service. But from your question, I thought that when a lot of files are converted, the execution time might be over 6 minutes. So in this sample script, I conver the files with the files.copy method of Drive API using Batch request.

    Sample script:

    When you run the script, please set the parameters to the function of main(). And run main().

    // Get file IDs of Microsoft Excel files in a specific folder including subfolders.
    function getFileIds(folder, fileIds, q) {
      var files = folder.searchFiles(q);
      while (files.hasNext()) {
        fileIds.push(files.next().getId());
      }
      var folders = folder.getFolders();
      while (folders.hasNext()) {
        getFileIds(folders.next(), fileIds, q);
      }
      return fileIds;
    }
    
    // Convert Microsoft Docs to Google Docs
    function convertToGoogleDocs(fileIds, dest, to) {
      var limit = 100;
      var split = Math.ceil(fileIds.length / limit);
      var reqs = [];
      for (var i = 0; i < split; i++) {
        var boundary = "xxxxxxxxxx";
        var payload = fileIds.splice(0, limit).reduce(function(s, e, i) {
          s += "Content-Type: application/http\r\n" +
            "Content-ID: " + i + "\r\n\r\n" +
            "POST https://www.googleapis.com/drive/v3/files/" + e + "/copy" + "\r\n" +
            "Content-Type: application/json; charset=utf-8\r\n\r\n" +
            JSON.stringify({"parents": [dest], "mimeType": to}) + "\r\n" +
            "--" + boundary + "\r\n";
          return s;
        }, "--" + boundary + "\r\n");
        var params = {
          method: "post",
          contentType: "multipart/mixed; boundary=" + boundary,
          payload: payload,
          headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()},
          muteHttpExceptions: true,
        };
        var req = UrlFetchApp.getRequest("https://www.googleapis.com/batch/drive/v3", params);
        reqs.push(req);
      }
      return UrlFetchApp.fetchAll(reqs);
    }
    
    // Please run this function.
    function main() {
      var sourceFolderId = "###"; // Folder ID including source files. Please set this.
      var destinationFolderId = "###"; // Folder ID that the converted files are put. Please set this.
    
      var from = [MimeType.RTF, MimeType.MICROSOFT_WORD_LEGACY]; // Source mimeType
      var to = MimeType.GOOGLE_DOCS; // Destination mimeType
      var q = from.reduce(function(q, e, i) {return q += "mimeType='" + e + "'" + (i < from.length - 1 ? " or " : "")}, "");
      var fileIds = getFileIds(DriveApp.getFolderById(sourceFolderId), [], q);
      Logger.log(fileIds)
      var res = convertToGoogleDocs(fileIds, destinationFolderId, to);
      Logger.log(res);
    }
    

    Note:

    • If the file size is large, an error might occur.
    • When RTF file is retrieved by Drive API, there was the case that the mimeType becomes application/msword. So I searched both application/rtf and application/msword.
    • Unfortunately, in the current stage, the batch request cannot use the media blob. So I used the files.copy method. In this case, the files can be converted without using the media blob.

    References:

    If I misunderstood your question and this was not the result you want, I apologize.