上传自昨天以来损坏的二进制文件,解决方法? [英] Uploading binary files broken since yesterday, workaround?
问题描述
更新:我创建了一个问题:https://issuetracker.google.com/issues/150675170
我的网络应用程序运行良好,但现在突然上传的 pdf 文件损坏了.下面是一个小型简化示例,可用于重现该问题.
My web app worked well for a long time, but now suddenly the uploaded pdf files become corrupted. Below is a small reduced example that can be used to reproduce the issue.
查看上传的文件内容,貌似文件内容被当成文本处理了,有几个字符被替换为EF BF BD
,即'REPLACEMENT CHARACTER的UTF-8字节序列' (U+FFFD).
Looking at the uploaded file content, it looks like the file content is treated as text, and several characters are replaced with EF BF BD
, which is the UTF-8 byte sequence for 'REPLACEMENT CHARACTER' (U+FFFD).
例如,原始 PDF 文件的第一个字节:
For example, first bytes of the original PDF file:
25 50 44 46 2D 31 2E 34 0A 25 E2 E3 CF D3 0A 31 39 |%PDF-1.4
%âãÏÓ
19
25 50 44 46 2D 31 2E 34 0A 25 E2 E3 CF D3 0A 31 39 | %PDF-1.4
%âãÏÓ
19
它被上传为:
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
%����
19
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
%����
19
我不知道去哪里报告,我只希望谷歌员工能看到并修复它.
I'm not sure where to report it, I only hope that a Google employee will see it and fix it.
与此同时,也许熟悉 Google Apps Script 的人有一个解决方法的想法.
In the meanwhile, perhaps somebody familiar with Google Apps Script has an idea for a workaround.
下面是一个精简的小例子 - 部署,上传一个二进制文件,转到 Drive,在test"文件夹下找到它,下载它,观察它是否坏了.
Below is the small reduced example - deploy, upload a binary file, go to Drive, find it under the "test" folder, download it, observe that it's broken.
HTML 模板,文件名 test_form.html
:
HTML template, file name 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});
}
}
推荐答案
更新(2021 年 11 月): 问题已解决:https://issuetracker.google.com/issues/155109626
一种解决方法:在客户端对它进行 base64 编码,然后在服务器上对其进行 base64 解码.然后内容没有搞砸.举个例子:
One workaround: base64-encode it on the client side, then base64-decode it on the server. Then the contents is not screwed up. Here's an example:
HTML 模板,文件名 test_form.html
:
HTML template, file name 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});
}
}
这篇关于上传自昨天以来损坏的二进制文件,解决方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!