【发布时间】:2019-02-04 11:51:48
【问题描述】:
我正在尝试通过 multipart upload API v3.
这是文件内容的十六进制表示:
FF FE
由于某种原因,上述内容被编码为 UTF-8(我假设) 当我尝试发布它时,它包含在一个多部分有效负载中:
--BOUNDARY
Content-Type: application/json
{"name": "F.ini"}
--BOUNDARY
Content-Type: application/octet-stream
ÿþ <-- in the outbound request, this gets UTF-8 encoded
--BOUNDARY--
最终存储在服务器端的文件的十六进制表示:
C3 BF C3 BE
问题只出现在发送阶段:
如果我检查从文件中读取的内容的长度,我总是得到 2;
无论我使用FileReader#readAsBinaryString 还是FileReader#readAsArrayBuffer
(分别产生一个长度为 2 的字符串和一个 ArrayBuffer 和 byteLength 2)。
这是我用来生成多部分负载的最少代码:
file = picker.files[0]; // 'picker' is a file picker
reader = new FileReader();
reader.onload = function (e) {
content = e.target.result;
boundary = "BOUNDARY";
meta = '{"name": "' + file.name + '"}';
console.log(content.length); // gives 2 as expected
payload = [
"--" + boundary, "Content-Type: application/json", "", meta, "", "--" + boundary,
"Content-Type: application/octet-stream", "", content, "--" + boundary + "--"
].join("\r\n");
console.log(payload.length); // say this gives n
xhr = new XMLHttpRequest();
xhr.open("POST", "/", false);
xhr.setRequestHeader("Content-Type", "multipart/related; boundary=" + boundary);
xhr.send(payload); // this produces a request with a 'Content-Length: n+2' header
// (corresponding to the length increase due to UTF-8 encoding)
};
reader.readAsBinaryString(file);
我的问题有两个:
- 有没有办法避免这种自动 UTF-8 编码? (可能不会,因为 this answer 暗示 UTF-8 编码是 XHR 规范的一部分。)
- 如果不是,“通知”Drive API 我的文件内容是 UTF-8 编码的正确方法是什么?
我尝试了这些方法,但没有成功:
- 将
; charset=utf-8或; charset=UTF-8附加到二进制部分的Content-Type标头 - 对父请求的 HTTP 标头执行相同操作
(
Content-Type: multipart/related; boundary=blablabla, charset=utf-8; 还尝试用分号替换逗号)
- 将
我需要多部分 API,因为 AFAIU "simple" API
不允许我上传到文件夹
(它只接受文件名作为元数据,通过Slug HTTP 标头,
而多部分情况下的 JSON 元数据对象也允许指定 parent 文件夹 ID)。
(只是想提到这一点,因为“简单”的 API 可以正确处理事情
当我直接将File(来自选择器)或ArrayBuffer(来自FileReader#readAsArrayBuffer)作为 XHR 的有效负载发布时。)
我不想使用任何第三方库,因为
- 我想让事情尽可能轻松,并且
- 撇开重新发明轮子和最佳实践的东西,第三方库完成的任何事情都应该通过普通 JS 来实现(这只是 fun exercise)。
为了完整起见,我尝试通过 GDrive 网络界面上传相同的文件,并且上传得很好; 但是,Web 界面似乎对有效负载进行了 base64 编码,我希望避免这种情况 (因为它不必要地膨胀了有效载荷,尤其是对于更大的有效载荷,这是我的最终目标)。
【问题讨论】:
-
我可以问你关于你的问题吗?虽然我不确定我是否能理解您的情况,但是使用
reader.readAsArrayBuffer(file)而不是reader.readAsBinaryString(file)怎么样?顺便说一句,从您的脚本来看,似乎没有 Drive API 的端点,也没有包含访问令牌的标头。实际的脚本有吗? -
readAsArrayBuffer和readAsBinaryString都给了我相同的输出大小 (2);但由于我想编写一个多部分有效负载,我确实需要将内容作为字符串读取。关于代码@Tanaike,你说得对,没有 Drive API 端点/凭证;这是我为上传到本地服务器 (localhost) 以进行测试而编写的最小 sn-p,但编码行为(“膨胀”?)保持不变。 -
感谢您的回复。从您的回复中,我发布了一个答案。你能确认一下吗?如果这不是您想要的,我很抱歉。
-
我的回答是否向您展示了您想要的结果?你能告诉我吗?这对我学习也很有用。如果这可行,与您有相同问题的其他人也可以将您的问题作为可以解决的问题。如果您对我的回答有疑问,请随时告诉我。我想学习解决你的问题。
-
对不起,我直到现在才有机会尝试这个;它完美无缺!将您的答案标记为已接受:)
标签: javascript file-upload character-encoding google-drive-api multipart