AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / coding / Perguntas / 78056953
Accepted
soleil
soleil
Asked: 2024-02-26 01:26:41 +0800 CST2024-02-26 01:26:41 +0800 CST 2024-02-26 01:26:41 +0800 CST

Problemas de permissão ao excluir arquivos com a API do Google Drive em Ruby

  • 772

Eu tenho um script do Google Apps que cria arquivos json a partir de guias de planilhas:

function makeJSON() {
  var spreadsheetId = 'someId'; 
  var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
  var sheets = spreadsheet.getSheets();
  var urls = []; // Array to store the URLs of the created files

  for (var i =  1; i < sheets.length; i++) {
    var sheet = sheets[i];
    var data = sheet.getRange(3,  1, sheet.getLastRow() -  2, sheet.getLastColumn()).getValues();
    var headers = sheet.getRange(2,  1,  1, sheet.getLastColumn()).getValues()[0];

    var objects = data.map(function(row) {
    var obj = {};
    for (var j =  0; j < headers.length; j++) {
      //process data
    }
    
    return obj;
    });


     // Convert the array of objects to a JSON string
    var json = JSON.stringify(objects, null,  2);
    
    // Create a blob from the JSON string
    var blob = Utilities.newBlob(json, 'application/json', sheet.getName() + '.json');

    var folder = DriveApp.getFolderById('someId');
    var file = folder.createFile(blob);

    file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT); //I don't like making these publicly editable but it seems I'm forced to in order to be able to download/delete them via ruby script
    
    // Get the file ID
    var fileId = file.getId();
    
    // Construct the direct download URL
    var directDownloadUrl = "https://drive.google.com/uc?export=download&id=" + fileId;
    
    // Add the direct download URL to the array
    urls.push(directDownloadUrl);
    
  }
  return urls;
}

function doGet() {
  var urls = makeJSON(); // Call the function to generate JSON files and get their URLs
  return ContentService.createTextOutput(JSON.stringify({urls: urls})).setMimeType(ContentService.MimeType.JSON);
}

Eu tenho um script Ruby que baixa todos esses arquivos do Google Drive. Essa parte funciona. Mas também quero excluí-los após o download:

drive_service = Google::Apis::DriveV3::DriveService.new
scope = 'https://www.googleapis.com/auth/drive'

authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open('google_client.json'),
  scope: scope
)

authorizer.fetch_access_token!

# Set the authorization for the Drive API client
drive_service.authorization = authorizer

# URL of your deployed web app that returns JSON file URLs
web_app_url = 'https://script.google.com/macros/s/digits/exec'

# Fetch the JSON data from the web app
response = URI.open(web_app_url).read
json_data = JSON.parse(response)

# Directory to save the JSON files
save_directory = 'downloads'

# Ensure the directory exists
FileUtils.mkdir_p(save_directory) unless File.directory?(save_directory)

json_data['urls'].each do |url|
  # Extract the file ID from the URL
  file_id = url.split('id=')[1]
   
  # Fetch the file's metadata using the Google Drive API
  file_metadata = drive_service.get_file(file_id, fields: 'name')
   
  # Extract the file name
  file_name = file_metadata.name
   
  # Construct the direct download URL
  direct_download_url = "https://drive.google.com/uc?export=download&id=#{file_id}"
   
  # Construct the full path
  file_path = File.join(save_directory, file_name)
   
  # Download the file
  URI.open(direct_download_url) do |source|
    File.open(file_path, 'wb') do |file|
      file.write(source.read)
    end
  end
  puts "Saved #{file_name} to #{save_directory}"

  # Delete the file from Google Drive
  drive_service.delete_file(file_id) #THIS LINE THROWS THE ERROR
end

Aqui está o erro:

/Users/me/.rvm/gems/ruby-2.7.2/gems/google-apis-core-0.14.0/lib/google/apis/core/http_command.rb:244:in `check_status': insufficientFilePermissions: The user does not have sufficient permissions for this file. (Google::Apis::ClientError)

Acho que o problema é que no meu script Ruby as credenciais são da minha conta de serviço ( [email protected] ) e os arquivos no Google Drive são de propriedade de "Me" ( [email protected] ). Mas não consigo descobrir como torná-los propriedade da minha conta de serviço ou como executar o script com as credenciais normais da minha conta de e-mail. Quando você cria contas de serviço no console do Cloud, você é forçado a usar *.iam.gserviceaccount.comcontas.

A pasta do Google Drive é compartilhada com minha conta de serviço. Todos os arquivos nele contidos são de minha propriedade e minha conta de serviço tem permissões de editor em todos eles.

Dito isso, como posso excluir esses arquivos do Google Drive depois de baixá-los? Os arquivos se acumulam rapidamente e preciso manter esse diretório limpo.

  • 1 1 respostas
  • 27 Views

1 respostas

  • Voted
  1. Best Answer
    Tanaike
    2024-02-26T07:22:01+08:002024-02-26T07:22:01+08:00

    Na sua situação, como uma abordagem simples, que tal excluir o arquivo em Web Apps? Quando isso estiver refletido em seu script, que tal a seguinte modificação?

    Com esta modificação, após o download do arquivo, ele é excluído com Web Apps.

    Script do Google Apps:

    Antes de usar este script, ative a API Drive v3 em serviços avançados do Google .

    function makeJSON(e) { // Modified
      // Added
      if (e.parameter.deleteFile) {
        Drive.Files.remove(e.parameter.deleteFile); // or Drive.Files.remove(e.parameter.deleteFile, { supportsAllDrives: true });
        return [];
      }
    
      var spreadsheetId = 'someId'; 
      var spreadsheet = SpreadsheetApp.openById(spreadsheetId);
      var sheets = spreadsheet.getSheets();
      var urls = []; // Array to store the URLs of the created files
    
      for (var i =  1; i < sheets.length; i++) {
        var sheet = sheets[i];
        var data = sheet.getRange(3,  1, sheet.getLastRow() -  2, sheet.getLastColumn()).getValues();
        var headers = sheet.getRange(2,  1,  1, sheet.getLastColumn()).getValues()[0];
    
        var objects = data.map(function(row) {
        var obj = {};
        for (var j =  0; j < headers.length; j++) {
          //process data
        }
        
        return obj;
        });
    
    
         // Convert the array of objects to a JSON string
        var json = JSON.stringify(objects, null,  2);
        
        // Create a blob from the JSON string
        var blob = Utilities.newBlob(json, 'application/json', sheet.getName() + '.json');
    
        var folder = DriveApp.getFolderById('someId');
        var file = folder.createFile(blob);
    
        file.setSharing(DriveApp.Access.ANYONE, DriveApp.Permission.EDIT); //I don't like making these publicly editable but it seems I'm forced to in order to be able to download/delete them via ruby script
        
        // Get the file ID
        var fileId = file.getId();
        
        // Construct the direct download URL
        var directDownloadUrl = "https://drive.google.com/uc?export=download&id=" + fileId;
        
        // Add the direct download URL to the array
        urls.push(directDownloadUrl);
        
      }
      return urls;
    }
    
    function doGet(e) { // Modified
      var urls = makeJSON(e); // Modified
      return ContentService.createTextOutput(JSON.stringify({urls: urls})).setMimeType(ContentService.MimeType.JSON);
    }
    

    Rubi:

    drive_service = Google::Apis::DriveV3::DriveService.new
    scope = 'https://www.googleapis.com/auth/drive'
    
    authorizer = Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: File.open('google_client.json'),
      scope: scope
    )
    
    authorizer.fetch_access_token!
    
    # Set the authorization for the Drive API client
    drive_service.authorization = authorizer
    
    # URL of your deployed web app that returns JSON file URLs
    web_app_url = 'https://script.google.com/macros/s/digits/exec'
    
    # Fetch the JSON data from the web app
    response = URI.open(web_app_url).read
    json_data = JSON.parse(response)
    
    # Directory to save the JSON files
    save_directory = 'downloads'
    
    # Ensure the directory exists
    FileUtils.mkdir_p(save_directory) unless File.directory?(save_directory)
    
    json_data['urls'].each do |url|
      # Extract the file ID from the URL
      file_id = url.split('id=')[1]
       
      # Fetch the file's metadata using the Google Drive API
      file_metadata = drive_service.get_file(file_id, fields: 'name')
       
      # Extract the file name
      file_name = file_metadata.name
       
      # Construct the direct download URL
      direct_download_url = "https://drive.google.com/uc?export=download&id=#{file_id}"
       
      # Construct the full path
      file_path = File.join(save_directory, file_name)
       
      # Download the file
      URI.open(direct_download_url) do |source|
        File.open(file_path, 'wb') do |file|
          file.write(source.read)
        end
      end
      puts "Saved #{file_name} to #{save_directory}"
    
      # Delete the file from Google Drive
    
      # removed: drive_service.delete_file(file_id) #THIS LINE THROWS THE ERROR
      URI.open(web_app_url + "?deleteFile=#{file_id}") # Modified
    
    end
    

    Observação:

    • Ao modificar o script do Google Apps de aplicativos da Web, modifique a implantação como uma nova versão. Com isso, o script modificado é refletido nos aplicativos da Web. Por favor, tenha cuidado com isso.

    • Você pode ver os detalhes disso em meu relatório " Reimplementando aplicativos da Web sem alterar a URL dos aplicativos da Web para o novo IDE (autor: eu) ".

    • 1

relate perguntas

  • Adicionar número de série para atividade de cópia ao blob

  • A fonte dinâmica do empacotador duplica artefatos

  • Selecione linhas por grupo com 1s consecutivos

  • Lista de chamada de API de gráfico subscritoSkus estados Privilégios insuficientes enquanto os privilégios são concedidos

  • Função para criar DFs separados com base no valor da coluna

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle?

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Quando devo usar um std::inplace_vector em vez de um std::vector?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Marko Smith

    Estou tentando fazer o jogo pacman usando apenas o módulo Turtle Random e Math

    • 1 respostas
  • Martin Hope
    Aleksandr Dubinsky Por que a correspondência de padrões com o switch no InetAddress falha com 'não cobre todos os valores de entrada possíveis'? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge Por que esse código Java simples e pequeno roda 30x mais rápido em todas as JVMs Graal, mas não em nenhuma JVM Oracle? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer Quando devo usar um std::inplace_vector em vez de um std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB Por que o GCC gera código que executa condicionalmente uma implementação SIMD? 2024-02-17 06:17:14 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve