base64 from js download as binary
От: vaa  
Дата: 21.03.23 02:15
Оценка:
Плагин криптопро работает с base64 данными.
Поэтому подписи и шифр отгружаются клиенту в текстовом формате (enc).
А хочется в двоичном (p7e). Можно конечно шифр отправлять на сервер и оттуда загружать преобразованный.
Но может спецы знают как преобразовать данные в браузере?
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re: base64 from js download as binary
От: Igorxz  
Дата: 23.03.23 13:27
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>Плагин криптопро работает с base64 данными.

vaa>Поэтому подписи и шифр отгружаются клиенту в текстовом формате (enc).
vaa>А хочется в двоичном (p7e). Можно конечно шифр отправлять на сервер и оттуда загружать преобразованный.
vaa>Но может спецы знают как преобразовать данные в браузере?

let create_blob_from_base64String = function (base64String, contentType) {
    const byteCharacters = atob(base64String);
    const byteNumbers = new Array(byteCharacters.length);
    for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);
    const blob = new Blob([byteArray], { type: contentType || 'text/json' });
    return (blob);
}


example:
create_blob_from_base64String("TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0\n"+
"aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1\n"+
"c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0\n"+
"aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdl\n"+
"LCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=")
Отредактировано 23.03.2023 13:29 Igorxz . Предыдущая версия .
Re[2]: base64 from js download as binary
От: vaa  
Дата: 24.03.23 03:29
Оценка:
Здравствуйте, Igorxz, Вы писали:

I>Здравствуйте, vaa, Вы писали:


vaa>>Плагин криптопро работает с base64 данными.

vaa>>Поэтому подписи и шифр отгружаются клиенту в текстовом формате (enc).
vaa>>А хочется в двоичном (p7e). Можно конечно шифр отправлять на сервер и оттуда загружать преобразованный.
vaa>>Но может спецы знают как преобразовать данные в браузере?

I>
I>let create_blob_from_base64String = function (base64String, contentType) {
I>    const byteCharacters = atob(base64String);
I>    const byteNumbers = new Array(byteCharacters.length);
I>    for (let i = 0; i < byteCharacters.length; i++) {
I>        byteNumbers[i] = byteCharacters.charCodeAt(i);
I>    }
I>    const byteArray = new Uint8Array(byteNumbers);
I>    const blob = new Blob([byteArray], { type: contentType || 'text/json' });
I>    return (blob);
I>}
I>




Спасибо! Я правда немного не так сделал, у меня кусками данные. Так отработало.
    function _base64ToArrayBuffer(base64String) {
        console.log(base64String);
        const byteCharacters = atob(base64String);
        const byteNumbers = new Array(byteCharacters.length);
        for (let i = 0; i < byteCharacters.length; i++) {
            byteNumbers[i] = byteCharacters.charCodeAt(i);
        }
        return byteNumbers;
    }
    arr = arr.concat(_base64ToArrayBuffer(chunk));
    new Blob([arr], { type: "octet/stream" });


Но все равно облом. Похоже ограничение размера массива где-то в районе 64Мб, исходный файл 81Мб, чанк 1МБ, на 77% такая шляпа:
 Uncaught (in promise) RangeError: Invalid array length
    at Array.concat (<anonymous>)
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[3]: base64 from js download as binary
От: Igorxz  
Дата: 24.03.23 13:50
Оценка:
Здравствуйте, vaa, Вы писали:

vaa>Спасибо! Я правда немного не так сделал, у меня кусками данные. Так отработало.

vaa>
vaa>    function _base64ToArrayBuffer(base64String) {
vaa>        console.log(base64String);
vaa>        const byteCharacters = atob(base64String);
vaa>        const byteNumbers = new Array(byteCharacters.length);
vaa>        for (let i = 0; i < byteCharacters.length; i++) {
vaa>            byteNumbers[i] = byteCharacters.charCodeAt(i);
vaa>        }
vaa>        return byteNumbers;
vaa>    }
vaa>    arr = arr.concat(_base64ToArrayBuffer(chunk));
vaa>    new Blob([arr], { type: "octet/stream" });
vaa>


vaa>Но все равно облом. Похоже ограничение размера массива где-то в районе 64Мб, исходный файл 81Мб, чанк 1МБ, на 77% такая шляпа:

vaa>
vaa> Uncaught (in promise) RangeError: Invalid array length
vaa>    at Array.concat (<anonymous>)
vaa>


странно. ну, у меня, вот такой код отрабатывает без ошибок. прям в консоли.
const byteNumbers = new Array(Math.pow(2, 30))

тему надо исследовать глубжее.
Re[4]: base64 from js download as binary
От: vaa  
Дата: 27.03.23 01:54
Оценка:
Здравствуйте, Igorxz, Вы писали:



I>странно. ну, у меня, вот такой код отрабатывает без ошибок. прям в консоли.

I>
I>const byteNumbers = new Array(Math.pow(2, 30))
I>

I>тему надо исследовать глубжее.
непонятно, размер логирую, не отличается от предыдущих порций
взял другой файл чуть большего размера, примерно в том же месте упало.
Переписал
    var add = _base64ToArrayBuffer(data);
                for (let i = 0; i < add.length; i++) {
                    arr.push(add[i]);
                }
arr.push(...add); // <= вот так не работает при даже при data = 0.5МБ
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[5]: base64 from js download as binary
От: Igorxz  
Дата: 27.03.23 14:33
Оценка:
Здравствуйте, vaa, Вы писали:
I>>странно. ну, у меня, вот такой код отрабатывает без ошибок. прям в консоли.
I>>
I>>const byteNumbers = new Array(Math.pow(2, 30))
I>>

I>>тему надо исследовать глубжее.
vaa>непонятно, размер логирую, не отличается от предыдущих порций
vaa>взял другой файл чуть большего размера, примерно в том же месте упало.
vaa>Переписал
vaa>
vaa>    var add = _base64ToArrayBuffer(data);
vaa>                for (let i = 0; i < add.length; i++) {
vaa>                    arr.push(add[i]);
vaa>                }
vaa>arr.push(...add); // <= вот так не работает при даже при data = 0.5МБ
vaa>


ну, собсно, сам ресурс оперативной памяти ограничен. это понятно. теперь нужно понять: а есть какое-то ограничение именно со стороны браузеров.
судя по докам — его явного нет.
теперь дальше: выделяя память вот так:
const byteNumbers = new Array(Math.pow(2, 30))

мы на самом деле ничего не выделяем. пока не начинаем лезть уже непосредственно к это памяти.
не забываем, что джаваскрипт в браузере — это хрен знает какой уровень абстракции. чем выше по абстракции — тем больше сюрпризов/зависимостей.
(в т.ч. поэтому на всяких а-ля сях всегда можно будет сделать то, что нельзя на джаваскриптах) вощем, долго писать))
вот так работает:
let finita_arrays = new Array(250*1024);
for (let i = 0; i < finita_arrays.length; i++) {
 let arr = new Array(1024);
 for (let j = 0; j < arr.length; j++) {
    arr[ j ] = j;
 }
 finita_arrays[i] = arr;
}
const blob = new Blob(finita_arrays, { type: 'x/z' });
console.log(blob.size/(1024*1024));

=>
978.759765625 (мб)

в пике вкладка хрома сжирает > 4GB. ну и ясно, что все это машино-индивидуально.
Отредактировано 27.03.2023 14:35 Igorxz . Предыдущая версия .
Re[6]: base64 from js download as binary
От: vaa  
Дата: 28.03.23 01:58
Оценка:
Здравствуйте, Igorxz, Вы писали:

I>вот так работает:

I>
I>let finita_arrays = new Array(250*1024);
I>for (let i = 0; i < finita_arrays.length; i++) {
I> let arr = new Array(1024);
I> for (let j = 0; j < arr.length; j++) {
I>    arr[ j ] = j;
I> }
I> finita_arrays[i] = arr;
I>}
I>const blob = new Blob(finita_arrays, { type: 'x/z' });
I>console.log(blob.size/(1024*1024));
I>

I>=>
I>
I>978.759765625 (мб)
I>


Я кажется понял в чем дело. На СО чел указал на ограничения браузера по памяти console.memory
и в случае если создать массив через var arr = [], видимо потом добавляемые через arr = arr.concat байты преобразуются во float, обертка который занимает 50+ байт.
тогда и получаются искомые ~ 60Мб, парадокс в том, что поштучное добавление элементов работает.
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[7]: base64 from js download as binary
От: Igorxz  
Дата: 28.03.23 21:32
Оценка: +1
Здравствуйте, vaa, Вы писали:

vaa>Я кажется понял в чем дело. На СО чел указал на ограничения браузера по памяти console.memory

vaa>и в случае если создать массив через var arr = [], видимо потом добавляемые через arr = arr.concat байты преобразуются во float, обертка который занимает 50+ байт.
vaa>тогда и получаются искомые ~ 60Мб, парадокс в том, что поштучное добавление элементов работает.

тут дело в том, что, что такое:
arr = arr.concat(arr_2)

— это уже есть занятая память под два массива, нужно выделить память под третий, суммарно равный двум этим, туда скопировать данные. и это все существует вместе одновременно.
(не берем случаи, когда память резервируется (в менеджере памяти/аллокаторе) и там можно не перевыделять а занять резервируемую — т.к. это из джаваскрипта все равно неуправляемо — как повезет и т.д.)
в отличие от выделенного заранее одного и заполненного по байтно.
Re[8]: base64 from js download as binary
От: vaa  
Дата: 02.04.23 02:39
Оценка: 80 (1) +1
Здравствуйте, Igorxz, Вы писали:


I>тут дело в том, что, что такое:

I>
I>arr = arr.concat(arr_2)
I>

I>- это уже есть занятая память под два массива, нужно выделить память под третий, суммарно равный двум этим, туда скопировать данные. и это все существует вместе одновременно.
I>(не берем случаи, когда память резервируется (в менеджере памяти/аллокаторе) и там можно не перевыделять а занять резервируемую — т.к. это из джаваскрипта все равно неуправляемо — как повезет и т.д.)
I>в отличие от выделенного заранее одного и заполненного по байтно.

вообщем, решил проблему.

var arrayOne = new Uint8Array([2,4,8]);
var arrayTwo = new Uint8Array([16,32,64]);

var mergedArray = new Uint8Array(arrayOne.length + arrayTwo.length);
mergedArray.set(arrayOne);
mergedArray.set(arrayTwo, arrayOne.length);


файл в 200МБ успешно зашифрован поточным методом и выгружен на диск.
☭ ✊ В мире нет ничего, кроме движущейся материи.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.