Google App 脚本“异常:FILENAME.csv 超过最大文件大小”的解决方法?

Eri*_*ric 2 google-apps-script import-from-csv google-app-maker

我正在构建一个 Google App Maker 应用程序,它将用户上传的 Excel CSV 电子表格文件作为输入。我想过多种可能的解决方案来读取此文件中的数据,但每次都遇到此错误:“异常:FILENAME.csv 超出最大文件大小”。我尝试通过 parseCSV() 将数据提取到 Google Cloud SQL,通过 .getBlob().getDataAsString() 作为一个字符串读入并用“\n”分割,然后将所有数据写入 Google Docs 并尝试读取它从那里。但是,所有这些方法都导致了相同的错误。

是否有解决此最大文件大小问题的解决方法?

我曾考虑将文件拆分为较小的 CSV 文件,但我不确定如何执行此操作。

Tan*_*ike 5

您想将大型 CSV 文件转换为拆分的电子表格。如果我的理解是正确的,这个解决方法如何?

这种情况的问题和解决方法:

  1. 如此大的 CSV 文件转换为电子表格时,由于单元格总数和文件大小,无法直接转换为电子表格。而且当尝试拆分大文件时,也无法拆分,因为可以在 GAS 使用的 blob 小于 50 MB(52,428,800 字节)。

  2. 在我的环境中,当此示例脚本使用大小为 100 MB 的 CSV 文件时,将文件拆分为 10 MB 时,将块转换为电子表格大约需要 65 秒。在这种情况下,当 CSV 文件完全转换时,将被认为将超过执行 GAS 的限制时间(6 分钟)。

    • 为了避免这种情况,需要实现从大型 CSV 文件到多个电子表格的可恢复转换。

准备 :

要使用此示例脚本,请在高级 Google 服务和 API 控制台中启用 Drive API。

在高级 Google 服务中启用 Drive API v2

  • 在脚本编辑器上
    • 资源 -> 高级 Google 服务
    • 开启 Drive API v2

在 API 控制台启用 Drive API

  • 在脚本编辑器上
    • 资源 -> 云平台项目
    • 查看 API 控制台
    • 在入门中,单击启用 API 并获取密钥等凭据。
    • 在左侧,单击库。
    • 在搜索 API 和服务处,输入“驱动器”。然后单击 Drive API。
    • 单击启用按钮。
    • 如果 API 已经启用,请不要关闭。

示例脚本:

function createSplitSpreadsheet(obj) {
  var accessToken = ScriptApp.getOAuthToken();
  var baseUrl = "https://www.googleapis.com/drive/v3/files/";

  // Retrieve file size.
  var url1 = baseUrl + obj.fileId + "?fields=size";
  var params1 = {
    method: "get",
    headers: {Authorization: "Bearer " + accessToken},
  };
  var fileSize = Number(JSON.parse(UrlFetchApp.fetch(url1, {headers: {Authorization: "Bearer " + accessToken}}).getContentText()).size);

  // Calculate number of output files.
  if (obj.files == null) {
    obj.number = 1;
    obj.start = 0;
  }
  var start = obj.start;
  var end = start + obj.chunk;
  var useFileSize = fileSize - start;
  f = Math.floor(useFileSize / obj.chunk);
  f = useFileSize % obj.chunk > 0 ? f + 1 : f;
  if (f < obj.files || obj.files == null) {
    obj.files = f;
  }

  // Split large file by chunk size (bytes).
  var url2 = baseUrl + obj.fileId + "?alt=media";
  var i;
  for (i = 0; i < obj.files; i++) {
    var params = {
      method: "get",
      headers: {
        Authorization: "Bearer " + accessToken,
        Range: "bytes=" + start + "-" + end,
      },
    };
    var res = UrlFetchApp.fetch(url2, params).getContentText();
    var e = res.lastIndexOf("\n");
    start += e + 1;
    end = start + obj.chunk;
    Drive.Files.insert(
      {mimeType: MimeType.GOOGLE_SHEETS, title: obj.fileName + (i + obj.number)},
      Utilities.newBlob(res.substr(0, e), MimeType.CSV)
    );
  }

  // Return next start value if there is a next chunk for the resume.
  if (start < fileSize) {
    return {nextStart: start, nextNumber: i + obj.number};
  } else {
    return null;
  }
}

// Please run this function.
function main() {
    var obj = {
        fileId: "#####", // File ID of the large CSV file.
        chunk: 10485760, // 10MB Please modify this for your situation.
        files: 3, // Please input the number of files you want to convert.
        start: 0,
        fileName: "sample",
        number: 1, // Counter of output files. Please input this as a next number.
    };
    var nextStart = createSplitSpreadsheet(obj);
    Logger.log(nextStart);
}
Run Code Online (Sandbox Code Playgroud)

用法 :

当您使用此,请修改objmain()您的具体情况,并运行main()。示例案例如下。

它假设如下。

  • 您想将大小为 100 MB 的 CSV 文件转换为 10 个电子表格。
  • 一个块的大小为 10 MB。
  • CSV 文件每 3 处理一次。

在本示例中,每个示例obj如下。请obj在每次运行时输入每个。

  1. var obj = {fileId: "#####", chunk: 10485760, files: 3, start: 0, fileName: "sample", number: 1}
    • {"nextStart": ### nextStart2 ###, "nextNumber": 4}从 返回createSplitSpreadsheet()
  2. var obj = {fileId: "#####", chunk: 10485760, files: 3, start: ### nextStart2 ###, fileName: "sample", number: 4}
    • {"nextStart": ### nextStart3 ###, "nextNumber": 7}从 返回createSplitSpreadsheet()
  3. var obj = {fileId: "#####", chunk: 10485760, files: 3, start: ### nextStart3 ###, fileName: "sample", number: 7}
    • {"nextStart": ### nextStart4 ###, "nextNumber": 10}从 返回createSplitSpreadsheet()
  4. var obj = {fileId: "#####", chunk: 10485760, files: 3, start: ### nextStart4 ###, fileName: "sample", number: 10}
    • null从 返回createSplitSpreadsheet()

通过此流程,从 100 MB 大小的 CSV 文件创建了 10 个电子表格。

如果null用于filesin objfiles则自动计算。但在这种情况下,执行 GAS 的限制时间可能已经结束。请注意这一点。

参考 :

如果这不是你想要的,我很抱歉。