Search code examples
javascriptgoogle-sheetsgoogle-apps-scriptgoogle-drive-api

Overwriting PDF File with Google Apps Scripts Causes Drive App to be unable to locate file


I have some code in Apps Script that saves a Google Sheet as a PDF.

I need to be able to update the PDF file when the form changes, without creating a new file and deleting the old one.

In theory, I think that what I have below should work. But when I make a call to the Advanced Drive Service's API, it says it cannot find the file, even though I am certain the File ID is correct and if call it in another context, e.g. to get its name, Drive seems to be able to find it.

    function replaceFile(theBlob, theFileId) 
{
  var oldFile = DriveApp.getFileById(theFileId);
  Logger.log(oldFile.getId());
  try
  {
    
    Drive.Files.update(
      {
        title: oldFile.getName(),
        mimeType: oldFile.getMimeType()
      },
      theFileId,
      theBlob,
      {
        convert: true, supportAllDrives: true
      }
    );
    
    Logger.log(Drive.Files.get('11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc', {supportsAllDrives: true}).getName());
    Logger.log("Success!");
    SpreadsheetApp.getActive().toast("PDF Updated With Success");
  }
  catch (error)
  {
    Logger.log(error);
    SpreadsheetApp.getActive().toast(error);
    
  }

}
function test1 ()
{
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var pdfBlob = spreadsheet.getAs('application/pdf');
  replaceFile(pdfBlob,"1UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc");
}

Here is the error I get:

GoogleJsonResponseException: API call to drive.files.get failed with error: File not found: 11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc.

Here is the link to the code I based mine on: How can I overwrite the old file with app script when I save the file?

As far as I can tell what I have should work.

EDIT: here is my updated script, when I retreive the file with the Drive.Files.get() function it works, but with Drive.Files.update() it says the file is not found.

function replaceFile(theBlob, theFileId) 
{
  var oldFile = DriveApp.getFileById(theFileId);
  Logger.log(oldFile.getId());
  try
  {
    
    Drive.Files.update(
  { mimeType: oldFile.getMimeType() },
    theFileId,
    theBlob,
  { supportAllDrives: true }
  );
    
    Logger.log(Drive.Files.get(theFileId, {supportsAllDrives: true}).getName());
    Logger.log("Success!");
    SpreadsheetApp.getActive().toast("PDF Updated With Success");
    
    
  }
  catch (error)
  {
    Logger.log(error);
    SpreadsheetApp.getActive().toast(error);
    
  }

}

function test1 ()
{
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  SpreadsheetApp.flush();
  var pdfBlob = spreadsheet.getAs('application/pdf');
  replaceFile(pdfBlob,"1ZuftxjH8t6WVKR-sxHl98iywhRPDHnC-");
}

Solution

  • From your showing error message GoogleJsonResponseException: API call to drive.files.get failed with error: File not found: 11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc., I guessed that the other part of your script worked.

    And, from this error message, it seems that the file of file ID 11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc is not existing at Drive.Files.get('11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc', {supportsAllDrives: true}).getName().

    When I saw your showing script, your file ID of theFileId is as follows.

    1UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc
    

    But, at Drive.Files.get('11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc', {supportsAllDrives: true}).getName(), you use the file ID as follows.

    11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc
    

    I guessed that in this case, the 1st character 1 is required to be removed. I guessed that this might be the reason for your current issue.

    If you want to use theFileId at Drive.Files.get('11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc', {supportsAllDrives: true}).getName(), how about the following modification?

    From:

    Drive.Files.get('11UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc', {supportsAllDrives: true}).getName()
    

    To:

    Drive.Files.get(theFileId, {supportsAllDrives: true}).getName()
    

    or

    Drive.Files.get('1UNOvk1qO5yR0Rs0xF3LrWaxYEgOxlRfc', {supportsAllDrives: true}).getName()
    

    Also, in order to retrieve the file name using Drive.Files.get of Drive API v3, you can also use Drive.Files.get(theFileId, {supportsAllDrives: true}).name.

    Note:

    • By the way, in the current stage, when Drive API is enabled at Advanced Google services, v3 is used as the default version. I'm not sure about your actual situation. But, if you are using Drive API v3, title: oldFile.getName(), is required to be name: oldFile.getName(),. But in your situation, the request body might be {mimeType: oldFile.getMimeType()}. Also, in the case of Drive API v3, convert: true does not exist in the query parameter. So, how about the following modification?

      Drive.Files.update(
        { mimeType: oldFile.getMimeType() },
        theFileId,
        theBlob,
        { supportsAllDrives: true } // <--- Modified
      );
      
    • By the way, if the latest Spreadsheet is not reflected, please add SpreadsheetApp.flush() just after the line of var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); and test it again.

    Reference: