AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 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

在 ruby​​ 中使用 Google Drive API 删除文件时出现权限问题

  • 772

我有一个 Google Apps 脚本,可以从电子表格选项卡创建 json 文件:

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);
}

我有一个 ruby​​ 脚本,可以从 Google Drive 下载所有这些文件。那部分有效。但我也想在下载后删除它们:

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

这是错误:

/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)

我认为问题在于,在我的 ruby​​ 脚本中,凭据来自我的服务帐户([email protected]),而 Google Drive 上的文件归“我”所有([email protected])。但我不知道如何让它们首先归我的服务帐户所有,也不知道如何使用我的常规电子邮件帐户凭据运行脚本。当您在云控制台中创建服务帐户时,它会强制您使用*.iam.gserviceaccount.com帐户。

Google 云端硬盘文件夹与我的服务帐户共享。其中的所有文件均归“我”所有,并且我的服务帐户对所有文件都具有编辑者权限。

那么,话虽如此,下载这些文件后如何从 Google 云端硬盘中删除它们呢?文件堆积得很快,我需要保持这个目录干净。

  • 1 1 个回答
  • 27 Views

1 个回答

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

    在您的情况下,作为一种简单的方法,删除 Web Apps 中的文件怎么样?当这反映在您的脚本中时,以下修改如何?

    通过此修改,下载文件后,该文件将随 Web Apps 一起删除。

    谷歌应用脚​​本:

    在使用此脚本之前,请在高级 Google 服务中启用 Drive API v3。

    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);
    }
    

    红宝石:

    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
    

    笔记:

    • 当您修改Web Apps的Google Apps脚本时,请将部署修改为新版本。这样,修改后的脚本就会反映在Web Apps中。请注意这一点。

    • 您可以在我的报告“重新部署 Web 应用程序而不更改新 IDE 的 Web 应用程序的 URL(作者:我) ”中查看详细信息。

    • 1

相关问题

  • 将复制活动的序列号添加到 Blob

  • Packer 动态源重复工件

  • 选择每组连续 1 的行

  • 图形 API 调用列表 subscribedSkus 状态权限不足,但已授予权限

  • 根据列值创建单独的 DF 的函数

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行?

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    何时应使用 std::inplace_vector 而不是 std::vector?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Martin Hope
    Aleksandr Dubinsky 为什么 InetAddress 上的 switch 模式匹配会失败,并出现“未涵盖所有可能的输入值”? 2024-12-23 06:56:21 +0800 CST
  • Martin Hope
    Phillip Borge 为什么这个简单而小的 Java 代码在所有 Graal JVM 上的运行速度都快 30 倍,但在任何 Oracle JVM 上却不行? 2024-12-12 20:46:46 +0800 CST
  • Martin Hope
    Oodini 具有指定基础类型但没有枚举器的“枚举类”的用途是什么? 2024-12-12 06:27:11 +0800 CST
  • Martin Hope
    sleeptightAnsiC `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它? 2024-11-09 07:18:53 +0800 CST
  • Martin Hope
    The Mad Gamer 何时应使用 std::inplace_vector 而不是 std::vector? 2024-10-29 23:01:00 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST
  • Martin Hope
    MarkB 为什么 GCC 生成有条件执行 SIMD 实现的代码? 2024-02-17 06:17:14 +0800 CST

热门标签

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

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve