0

I'm looking to get this bit of app script to replace existing files in the google drive instead of writing duplicates of them when it identifies that the file already exists in the drive. I've tried a few things but I can't get it to work as intended.

It is requesting that I add additional information, but my question doesn't need any more context. I'm adding this as filler.

  // GLOBALS
//Array of file extension which you would like to extract to Drive
var fileTypesToExtract = ['csv'];
//Name of the folder in google drive i which files will be put
var folderName = 'GmailToDrive';
//Name of the label which will be applied after processing the mail message
var labelName = 'GmailToDrive';



function GmailToDrive(){
  //build query to search emails
  var query = '';
  //filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+formattedDate+
  for(var i in fileTypesToExtract){
 query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
  }
  query = 'in:inbox has:nouserlabels ' + query;
  var threads = GmailApp.search(query);
  var label = getGmailLabel_(labelName);
  var parentFolder;
  if(threads.length > 0){
    parentFolder = getFolder_(folderName);
  }
  var root = DriveApp.getRootFolder();
  for(var i in threads){
    var mesgs = threads[i].getMessages();
 for(var j in mesgs){
      //get attachments
      var attachments = mesgs[j].getAttachments();
      for(var k in attachments){
        var attachment = attachments[k];
        var isDefinedType = checkIfDefinedType_(attachment);
     if(!isDefinedType) continue;
     var attachmentBlob = attachment.copyBlob();
        var file = DriveApp.createFile(attachmentBlob);
        parentFolder.addFile(file);
        root.removeFile(file);
      }
 }
 threads[i].addLabel(label);
  }
}

//This function will get the parent folder in Google drive
function getFolder_(folderName){
  var folder;
  var fi = DriveApp.getFoldersByName(folderName);
  if(fi.hasNext()){
    folder = fi.next();
  }
  else{
    folder = DriveApp.createFolder(folderName);
  }
  return folder;
}

//getDate n days back
// n must be integer
function getDateNDaysBack_(n){
  n = parseInt(n);
  var date = new Date();
  date.setDate(date.getDate() - n);
  return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy/MM/dd');
}

function getGmailLabel_(name){
  var label = GmailApp.getUserLabelByName(name);
  if(!label){
 label = GmailApp.createLabel(name);
  }
  return label;
}

//this function will check for filextension type.
// and return boolean
function checkIfDefinedType_(attachment){
  var fileName = attachment.getName();
  var temp = fileName.split('.');
  var fileExtension = temp[temp.length-1].toLowerCase();
  if(fileTypesToExtract.indexOf(fileExtension) !== -1) return true;
  else return false;
}
Chris Hart
  • 17
  • 2
  • 8
  • Welcome to StackOverFlow please take this opportunity to take the [tour] and learn how to [ask] and provide [mcve]. And if you receive an answer that helps you to resolve your problem please check it off so that everyone can see that the problem is resolved. Generally, we like to see the code that you have are having a problem with and a description of what you have tried. If you successfully integrate all of these suggestions into your question then your much more likely to get a quick resolution to your problem. – Cooper Mar 12 '19 at 21:10

1 Answers1

2
  • When a file is created by var file = DriveApp.createFile(attachmentBlob), if the same filename with attachmentBlob is existing, you want to replace the existing file to new file created with attachmentBlob.

If my understanding is correct, how about this modification? Please think of this as just one of several solutions. The flow of this modified script is as follows.

  1. Retrieve the filename of attachment.
  2. If there is the file which is the same filename with the retrieved filename, the existing file is deleted.
  3. Create new file with attachment.

Modified script:

Please modify as follows. When this modification is reflected, the existing file is put to the trash box. So please be careful this.

From:
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
parentFolder.addFile(file);
root.removeFile(file);
To:
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
  var file = existingFile.next();
  file.setTrashed(true);
}
var file = DriveApp.createFile(attachmentBlob);
parentFolder.addFile(file);
root.removeFile(file);

Note:

  • This modified script supposes that there is only one duplicated file in your drive. If there are several files with the same filename, please tell me.
  • file.setTrashed(true) just puts a file to the trash box. If you want to completely delete the file, please replace file.setTrashed(true); to the following script. The following script used the delete method of Drive API.
Script for completely deleting file:
var url = "https://www.googleapis.com/drive/v3/files/" + file.getId();
var params = {
  method: "delete",
  headers: {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}
}
UrlFetchApp.fetch(url, params);

References:

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

Edit:

If you want to overwrite attachmentBlob to the existing file which is the same filename with attachmentBlob, you can use the following script.

When you use this script, please enable Drive API at Advanced Google Services and API console. You can see about this at here.

Modified script:

From:
var attachmentBlob = attachment.copyBlob();
var file = DriveApp.createFile(attachmentBlob);
parentFolder.addFile(file);
root.removeFile(file);
To:
var attachmentBlob = attachment.copyBlob();
var existingFile = DriveApp.getFilesByName(attachment.getName());
if (existingFile.hasNext()) {
  var file = existingFile.next();
  Drive.Files.update({}, file.getId(), attachmentBlob);
} else { // Added
  var file = DriveApp.createFile(attachmentBlob); // Added
  parentFolder.addFile(file); // Added
  root.removeFile(file); // Added
}

Note:

  • When you run this script, the existing file is overwritten. So at first, please be careful this. So I recommend that it tests this script using a dummy file.

Reference:

Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • This is almost what I want, but I'd like the file to just be overwritten instead of deleted so that it's UUID in it's shared link stays the same, is that possible? – Chris Hart Mar 13 '19 at 20:30
  • @Chris Hart I'm really sorry for the inconvenience. I had thought that from your script, you want to create ``attachmentBlob`` as new file. I could understand about what you want to do as follows. You want to overwrite ``attachmentBlob`` to the existing file which is the same filename with ``attachmentBlob``. By this, I updated my answer. Could you please confirm it? **When you run this script, the existing file is overwritten. So at first, please be careful this. So I recommend that it tests this script using a dummy file.** – Tanaike Mar 13 '19 at 23:57
  • I have updated this script, but now it just tags the email and doesn't download anything at all to the file. – Chris Hart Mar 14 '19 at 19:38
  • @Chris Hart Thank you for replying. I apologize for the inconvenience. I forgot to add the create method when the file is not duplicated. I updated my answer. Could you please confirm it? By this update, when the attachment file is not duplicated, new file is created. And when the attachment file is duplicated, the file is overwritten to the existing file. – Tanaike Mar 14 '19 at 22:14