【问题标题】:Uploading binary files broken since yesterday, workaround?上传自昨天以来损坏的二进制文件,解决方法?
【发布时间】:2020-06-16 06:27:17
【问题描述】:

更新:我创建了一个问题:https://issuetracker.google.com/issues/150675170

我的网络应用程序运行良好很长时间,但现在突然上传的 pdf 文件损坏了。下面是一个小型简化示例,可用于重现该问题。

查看上传的文件内容,貌似文件内容被当作文本处理,有几个字符被替换为EF BF BD,即'REPLACEMENT CHARACTER'的UTF-8字节序列(U+FFFD)。

例如,原始 PDF 文件的第一个字节:

25 50 44 46 2D 31 2E 34 0A 25 E2 E3 CF D3 0A 31 39 | %PDF-1.4\n%âãÏÓ\n19

它被上传为:

25 50 44 46 2D 31 2E 34 0A 25 EF BF BD EF BF BD EF BF BD EF BF BD 0A 31 39 | %PDF-1.4\n%����\n19

我不确定在哪里报告,我只希望 Google 员工会看到并修复它。

与此同时,也许熟悉 Google Apps 脚本的人有一个解决方法的想法。

下面是一个简化的小例子 - 部署,上传一个二进制文件,转到 Drive,在“test”文件夹下找到它,下载它,观察它是否损坏。

HTML模板,文件名test_form.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>

<form id="test-form">
    <input type="file" id="test-file" name="test-file">
    <button id="submit-button" type="submit">Upload</button>
</form>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
    (function () {
        'use strict';

        $('#test-form').submit(function (e) {
            e.preventDefault(); // prevent form from submitting

            google.script.run
                .withFailureHandler(fileUploadedFailure)
                .withSuccessHandler(fileUploaded)
                .uploadFilesFrame(this);
        });

        function fileUploaded(status) {
            alert(status);
        }

        function fileUploadedFailure(error) {
            alert('Failed: ' + error.message);
        }
    })();
</script>
</body>
</html>

服务器代码,文件名Code.gs:

var rootFolderName = "test";

function doGet(e) {
  var template = HtmlService.createTemplateFromFile('test_form');
  return template.evaluate().setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

function uploadFilesFrame(form) {
  try {
    var fileBlob = form['test-file'];

    var rootFolder = DriveApp.getFoldersByName(rootFolderName);
    if (rootFolder.hasNext()) {
      rootFolder = rootFolder.next();
    } else {
      rootFolder = DriveApp.createFolder(rootFolderName);
    }

    var file = rootFolder.createFile(fileBlob);

    return JSON.stringify({"status": 'ok', "msg": file.getId()});
  } catch (error) {
    return JSON.stringify({"status": 'error', "data": error.stack});
  }
}

【问题讨论】:

标签: google-apps-script file-upload web-applications


【解决方案1】:

更新(2021 年 11 月):问题已解决: https://issuetracker.google.com/issues/155109626


一种解决方法:在客户端对其进行 base64 编码,然后在服务器上对其进行 base64 解码。然后内容没有搞砸。这是一个例子:

HTML模板,文件名test_form.html:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>

<form id="test-form">
    <input type="file" id="test-file" name="test-file">
    <input type="hidden" id="test-file2" name="test-file2">
    <input type="hidden" id="test-file-name" name="test-file-name">
    <button id="submit-button" type="submit">Upload</button>
</form>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
    (function () {
        'use strict';

        $('#test-form').submit(function (e) {
            var thisForm = this;
            e.preventDefault(); // prevent form from submitting

            var reader = new FileReader();
            reader.onload = function (event) {
                var result = event.target.result;
                var base64 = result.substr(result.indexOf(',') + 1);
                $('#test-file2').val(base64);
                
                var filename = $('#test-file').val().split('\\').pop();
                $('#test-file-name').val(filename);
                
                $('#test-file').prop('disabled', true);
                
                google.script.run
                    .withFailureHandler(fileUploadedFailure)
                    .withSuccessHandler(fileUploaded)
                    .uploadFilesFrame(thisForm);
            };
            reader.onerror = function (event) {
                alert("ERROR: " + event.target.error.code);
            };
            reader.readAsDataURL(document.getElementById('test-file').files[0]);
        });

        function fileUploaded(status) {
            alert(status);
        }

        function fileUploadedFailure(error) {
            alert('Failed: ' + error.message);
        }
    })();
</script>
</body>
</html>

服务器代码,文件名Code.gs:

var rootFolderName = "test";

function doGet(e) {
  var template = HtmlService.createTemplateFromFile('test_form');
  return template.evaluate().setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

function uploadFilesFrame(form) {
  try {
    var fileBlob = Utilities.newBlob(Utilities.base64Decode(form['test-file2']), 'application/octet-stream', form['test-file-name']);

    var rootFolder = DriveApp.getFoldersByName(rootFolderName);
    if (rootFolder.hasNext()) {
      rootFolder = rootFolder.next();
    } else {
      rootFolder = DriveApp.createFolder(rootFolderName);
    }

    var file = rootFolder.createFile(fileBlob);

    return JSON.stringify({"status": 'ok', "msg": file.getId()});
  } catch (error) {
    return JSON.stringify({"status": 'error', "data": error.stack});
  }
}

【讨论】:

    【解决方案2】:

    既然您阻止了提交的默认行为,如何尝试这种方式:

    我现在实际上在犹豫是否要告诉你这件事,因为我怀疑你比我更了解它。但是为了提供帮助并且可能看起来很愚蠢,我建议您尝试这种方式。

    <!DOCTYPE html>
    <html>
    <head>
    </head>
    <body>
    
    <form>
        <input type="file" id="test-file" name="test-file">
        <input type="button" value="Submit" onClick="this.parentNode" />
    </form>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script>
        function uploadFile(form) {
          google.script.run
          .withFailureHandler(fileUploadedFailure)
          .withSuccessHandler(fileUploaded)
          .uploadFilesFrame(form);
        }
        function fileUploaded(status) {
          alert(status);
        }
        function fileUploadedFailure(error) {
           alert('Failed: ' + error.message);
         }
    
    </script>
    </body>
    </html>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多