Я пытаюсь загрузить двоичный файл в Google Drive через
API многоэтапной загрузки v3 .
Вот шестнадцатеричное представление содержимого файла:
FF FE
По какой-то причине вышеуказанный контент кодируется как UTF-8 (я полагаю)
когда я пытаюсь POST его, заключенный в полезную нагрузку из нескольких частей:
--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? (Вероятно, нет, потому что
этот ответ
подразумевает, что кодировка 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 "простой" API
не позволяет мне загружать в папку
(он принимает только имя файла в качестве метаданных через HTTP-заголовок Slug
,
тогда как объект метаданных JSON в случае нескольких частей также позволяет указать идентификатор папки parent
).
(Просто подумал упомянуть об этом, потому что «простой» API обрабатывает вещи правильно
когда я непосредственно ПОСТАВЛЯЮ File
(от сборщика) или ArrayBuffer
(от FileReader#readAsArrayBuffer
) в качестве полезной нагрузки XHR.)
Я не хочу использовать какие-либо сторонние библиотеки, потому что
- Я хочу, чтобы все было как можно легче, а
- Не говоря уже о том, как изобретать руль и использовать лучшие практики, все, что может быть сделано сторонней библиотекой, должно выполняться и с помощью простого JS (это всего лишь веселое упражнение ).
Ради полноты я попытался загрузить тот же файл через веб-интерфейс GDrive, и он загрузился просто отлично;
однако веб-интерфейс, кажется, кодирует полезную нагрузку с помощью base64, чего я бы хотел избежать
(поскольку это излишне раздувает полезную нагрузку, особенно для больших полезных нагрузок, что является моей конечной целью).