Создание Blob или файла из двоичной строки JavaScript изменяет количество байтов?

Я играл с несколькими библиотеками шифрования JS (CryptoJS, SJCL) и обнаружил проблемы, связанные с API-интерфейсами Blob/File и двоичными строками JavaScript.

Я понял, что шифрование даже не очень актуально, так что здесь очень упрощенный сценарий. Просто прочитайте файл при использовании readAsBinaryString, а затем создайте Blob:

>>> reader.result
"GIF89a����ÿÿÿÿÿÿ!þCreated with GIMP�,�������D�;"
>>> reader.result.length
56
>>> typeof reader.result
"string"
>>> blob = new Blob([reader.result], {type: "image/gif"})
Blob { size=64, type="image/gif", constructor=function(), more...}

Я создал JSFiddle, который будет в основном делать следующее: он просто читает любой произвольный файл, создает из него blob и выводит длину vs size: http://jsfiddle.net/6L82t/1/

Похоже, что при создании Blob из "двоичной (javascript) строки" что-то с кодировкой символов заканчивается результатом.

Если используется недвоичный файл, вы увидите, что длины Blob и исходной двоичной строки идентичны.

Итак, есть что-то, что происходит при попытке создать Blob/File из строки Javascript, не являющейся открытым текстом, и мне нужно, чтобы этого не произошло. Я думаю, что это может иметь какое-то отношение к тому, что строки JS - это UTF-16?

Здесь есть (возможно) связанная тема: API-интерфейс HTML5 читается как текстовый и двоичный

Нужно ли, возможно, взять дешифрованные результаты (UTF-16) и "преобразовать" их в UTF-8 перед тем, как поместить их в Blob/File?

Работая с кем-то из # html5 на Freenode, мы определили, что если вы сразу читаете ArrayBuffer, а затем создаете blob из этого, сначала используя Uint8Array, байты работают просто отлично. Вы можете увидеть скрипку, которая по существу делает это здесь: http://jsfiddle.net/GH7pS/4/

Проблема в том, что, по крайней мере, в моем сценарии, я получаю двоичную строку и хотел бы выяснить, как напрямую преобразовать ее в Blob, чтобы затем я мог использовать загрузку html5, чтобы позволить пользователю нажмите, чтобы загрузить blob напрямую.

Спасибо!

Ответы

Ответ 1

Похоже, что при создании Blob из "двоичной (javascript) строки" что-то с кодировкой символов заканчивается результатом.

Да. Этот пост, который вы читаете, объясняет, как создается "двоичная строка".

Конструктор Blob отличается от

  • Пусть s является результатом преобразования [строки] в последовательность Unicode символов с использованием алгоритма для этого в WebIDL.
  • Кодируйте s как UTF-8 и добавьте полученные байты в [blob].

Мы определили, что если вы читаете ArrayBuffer напрямую, а затем создаете blob из этого, сначала используя Uint8Array, байты работают просто отлично.

Да, это то, как он должен работать. Просто выполните шифрование в Typed Array, где вы обрабатываете байты отдельно, а не на некоторой строке.

Проблема в том, что, по крайней мере, в моем сценарии, я получаю двоичную строку

Опять: постарайтесь не делать этого. бинарные строки устарели.

Я хотел бы выяснить, как напрямую преобразовать двоичную строку в Blob. Должен ли я взять дешифрованные результаты (UTF-16) и "преобразовать" их в UTF-8 перед тем, как поместить их в Blob/File?

Нет, лучше не пытайтесь преобразовывать строки. Вместо этого создайте Uint8Array (Uint8Array) для байтов, которые вы хотите получить из двоичной строки.

Это должно сделать это (непроверено):

var bytes = new Uint8Array(str.length);
for (var i=0; i<str.length; i++)
    bytes[i] = str.charCodeAt(i);