Muszę przekonwertować ciąg kodowania base64 na ArrayBuffer. Ciągi base64 są wprowadzane przez użytkownika, zostaną skopiowane i wklejone z wiadomości e-mail, więc nie ma ich tam, gdy strona jest ładowana. Chciałbym to zrobić w javascript bez wykonywania wywołania ajax do serwera, jeśli to możliwe.
Uważam, że te linki są interesujące, ale mi nie pomogły:
ArrayBuffer na ciąg zakodowany algorytmem Base64
chodzi o konwersję odwrotną, z ArrayBuffer na base64, a nie na odwrót
http://jsperf.com/json-vs-base64/2
wygląda to dobrze, ale nie mogę wymyślić, jak używać kodu.
Czy istnieje łatwy (może natywny) sposób przeprowadzenia konwersji? dzięki
bytes[i] = binary_string.charCodeAt(i);
może być źleKorzystanie z TypedArray.from :
Uint8Array.from(atob(base64_string), c => c.charCodeAt(0))
Wydajność do porównania z wersją pętli for odpowiedzi Goran.it.
źródło
Uint8Array.from
nadal ma niewielką zgodność z niektórymi przeglądarkami.ExecJS::RuntimeError: SyntaxError: Unexpected token: operator (>)
; (tory 5).buffer
właściwość tego, co jest zwracane zUint8Array
atob
lubbtoa
, po prostu musisz podać prawidłowe dane wejściowe.atob
wymaga prawidłowego ciągu base64, w przeciwnym razie zgłosi błąd. Ibtoa
potrzebuje prawidłowego ciągu bajtów (zwanego również ciągiem binarnym), który jest ciągiem zawierającym znaki z zakresu 0-255. Jeśli twój ciąg ma znaki spoza tego zakresu,btoa
zwróci błąd.Odpowiedź Goran.it nie działa z powodu problemu z Unicode w javascript - https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding .
Skończyło się na tym, że skorzystałem z funkcji podanej na blogu Daniela Guerrero: http://blog.danguer.com/2011/10/24/base64-binary-decoding-in-javascript/
Funkcja jest wymieniona na linku github: https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js
Użyj tych linii
var uintArray = Base64Binary.decode(base64_string); var byteArray = Base64Binary.decodeArrayBuffer(base64_string);
źródło
atob
.decodeArrayBuffer
zwraca wartość,ArrayBuffer
która ma rozmiar zawsze podzielny przez 3, czego nie rozumiem, jeśli jest to zgodne z projektem lub błędem. Zapytam w projekcie github.Właśnie znalazłem base64-arraybuffer, mały pakiet npm o niewiarygodnie wysokim wykorzystaniu, 5 milionów pobrań w zeszłym miesiącu (2017-08).
https://www.npmjs.com/package/base64-arraybuffer
Dla każdego, kto szuka czegoś w najlepszym standardowym rozwiązaniu, może to być to.
źródło
Rozwiązanie asynchroniczne , lepiej, gdy dane są duże:
// base64 to buffer function base64ToBufferAsync(base64) { var dataUrl = "data:application/octet-binary;base64," + base64; fetch(dataUrl) .then(res => res.arrayBuffer()) .then(buffer => { console.log("base64 to buffer: " + new Uint8Array(buffer)); }) } // buffer to base64 function bufferToBase64Async( buffer ) { var blob = new Blob([buffer], {type:'application/octet-binary'}); console.log("buffer to blob:" + blob) var fileReader = new FileReader(); fileReader.onload = function() { var dataUrl = fileReader.result; console.log("blob to dataUrl: " + dataUrl); var base64 = dataUrl.substr(dataUrl.indexOf(',')+1) console.log("dataUrl to base64: " + base64); }; fileReader.readAsDataURL(blob); }
źródło
Dla użytkowników Node.js:
const myBuffer = Buffer.from(someBase64String, 'base64');
myBuffer będzie typu Buffer, który jest podklasą Uint8Array. Niestety, Uint8Array NIE jest ArrayBuffer, o który prosił OP. Ale podczas manipulowania ArrayBuffer prawie zawsze zawijam go za pomocą Uint8Array lub czegoś podobnego, więc powinien być blisko tego, o co jest proszony.
źródło
Javascript to dobre środowisko programistyczne, więc wydaje się dziwne, ponieważ nie zapewnia rozwiązania tego małego problemu. Rozwiązania oferowane w innych miejscach na tej stronie są potencjalnie wolne. Oto moje rozwiązanie. Wykorzystuje wbudowaną funkcjonalność, która dekoduje adresy URL obrazu i dźwięku base64.
var req = new XMLHttpRequest; req.open('GET', "data:application/octet;base64," + base64Data); req.responseType = 'arraybuffer'; req.onload = function fileLoaded(e) { var byteArray = new Int8Array(e.target.response); // var shortArray = new Int16Array(e.target.response); // var unsignedShortArray = new Int16Array(e.target.response); // etc. } req.send();
Żądanie wysłania kończy się niepowodzeniem, jeśli łańcuch podstawowy 65 jest nieprawidłowo sformułowany.
Typ MIME (aplikacja / oktet) jest prawdopodobnie niepotrzebny.
Testowany w chromie. Powinien działać w innych przeglądarkach.
źródło
Access Denied
błąd, który wydaje się być ograniczeniem CORS.Czysty JS - bez łańcucha po środku (bez atob)
Piszę następującą funkcję, która konwertuje base64 w sposób bezpośredni (bez konwersji na string w środku). POMYSŁ
=
znakami, usuń jedną / dwie liczby z tablicy wyjściowejPoniższe rozwiązanie pozwala na przetwarzanie dużych łańcuchów wejściowych base64. Podobna funkcja do konwersji bajtów na base64 bez btoa jest TUTAJ
Pokaż fragment kodu
function base64ToBytesArr(str) { const abc = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]; // base64 alphabet let result = []; for(let i=0; i<str.length/4; i++) { let chunk = [...str.slice(4*i,4*i+4)] let bin = chunk.map(x=> abc.indexOf(x).toString(2).padStart(6,0)).join(''); let bytes = bin.match(/.{1,8}/g).map(x=> +('0b'+x)); result.push(...bytes.slice(0,3 - (str[4*i+2]=="=") - (str[4*i+3]=="="))); } return result; } // -------- // TEST // -------- let test = "Alice's Adventure in Wonderland."; console.log('test string:', test.length, test); let b64_btoa = btoa(test); console.log('encoded string:', b64_btoa); let decodedBytes = base64ToBytesArr(b64_btoa); // decode base64 to array of bytes console.log('decoded bytes:', JSON.stringify(decodedBytes)); let decodedTest = decodedBytes.map(b => String.fromCharCode(b) ).join``; console.log('Uint8Array', JSON.stringify(new Uint8Array(decodedBytes))); console.log('decoded string:', decodedTest.length, decodedTest);
źródło
const str = "dGhpcyBpcyBiYXNlNjQgc3RyaW5n" const encoded = new TextEncoder().encode(str) // is Uint8Array const buf = encoded.buffer // is ArrayBuffer
źródło