base64 문자열을 ArrayBuffer로 변환


98

base64 인코딩 문자열을 ArrayBuffer로 변환해야합니다. base64 문자열은 사용자 입력이며 이메일에서 복사하여 붙여 넣으므로 페이지가로드 될 때 존재하지 않습니다. 가능한 경우 서버에 아약스 호출을하지 않고 자바 스크립트에서 이것을하고 싶습니다.

흥미로운 링크를 찾았지만 도움이되지 않았습니다.

Base64 인코딩 문자열에 대한 ArrayBuffer

이것은 반대 방향이 아닌 ArrayBuffer에서 base64 로의 반대 변환에 ​​관한 것입니다.

http://jsperf.com/json-vs-base64/2

이것은 좋아 보이지만 코드를 사용하는 방법을 알 수 없습니다.

변환을 수행하는 쉬운 (아마도 네이티브) 방법이 있습니까? 감사

답변:


147

이 시도:

function _base64ToArrayBuffer(base64) {
    var binary_string = window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

3
여기서 실제로 무슨 일이 일어나고 있는지 설명 해주세요.
고빈다 Sakhare

4
꽤 간단합니다. 먼저 base64 문자열 (atob)을 디코딩 한 다음 디코딩 된 문자열과 길이가 같은 8 비트 부호없는 정수의 새로운 배열을 만듭니다. 그 후 문자열을 반복하고 문자열에있는 각 문자의 유니 코드 값으로 배열을 채 웁니다.
Goran.it

2
MDN에서 : Base64는 2 진 데이터를 기수 64 표현으로 변환하여 ASCII 문자열 형식으로 나타내는 유사한 2 진-텍스트 인코딩 체계의 그룹입니다. Uint8Array 유형 배열은 8 비트 부호없는 정수 배열을 나타내며, 데이터의 ASCII 표현 (8 비트 테이블이기도 함)으로 작업하고 있습니다.
Goran.it

3
이것은 올바르지 않습니다. 이는 자바 스크립트가 바이트를 문자열로 해석 할 수있게하여 실제 바이너리 인 데이터에 영향을줍니다.
Tomáš Zato-Monica 복원

4
문제는 a) 모든 바이트 시퀀스가 ​​유효한 유니 코드가 아니라는 것입니다. b) 유니 코드의 모든 문자가 1 바이트가 아니므 bytes[i] = binary_string.charCodeAt(i);로 잘못 될 수 있습니다
혼합

52

TypedArray.from 사용 :

Uint8Array.from(atob(base64_string), c => c.charCodeAt(0))

Goran.it 답변의 for 루프 버전과 비교할 성능.


2
이런 종류의 단일 라이너를 좋아하는 사람은 Uint8Array.from일부 브라우저와의 호환성이 거의 없다는 점을 명심하십시오 .
IzumiSy

2
atob 또는 btoa를 권장하지 마십시오 : developer.mozilla.org/en-US/docs/Web/API/WindowBase64/…
Kugel

rails 컴파일러는이 문자열을 처리 할 수 ​​없으며 실패합니다 ExecJS::RuntimeError: SyntaxError: Unexpected token: operator (>). (5 레일)
Avael KROSS

3
이것은 배열 버퍼가 아닙니다. 이것은 유형이 지정된 배열입니다. .buffer반환되는 속성을 통해 배열 버퍼에 액세스 할 수 있습니다.Uint8Array
oligofren

4
@Saites, atob또는 에는 아무런 문제가 없습니다 btoa. 유효한 입력을 제공하기 만하면됩니다. atob유효한 base64 문자열이 필요합니다. 그렇지 않으면 오류가 발생합니다. 그리고 btoa0-255 범위의 문자를 포함하는 문자열 인 유효한 바이트 문자열 (이진 문자열이라고도 함)이 필요합니다. 문자열에 해당 범위를 벗어난 문자 btoa가 있으면 오류가 발생합니다.
GetFree

34

- Goran.it의 대답 때문에 자바 스크립트의 유니 코드 문제로 인해 작동하지 않습니다 https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding .

결국 Daniel Guerrero의 블로그에 제공된 함수를 사용하게되었습니다. http://blog.danguer.com/2011/10/24/base64-binary-decoding-in-javascript/

함수는 github 링크에 나열되어 있습니다 : https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js

다음 행을 사용하십시오.

var uintArray = Base64Binary.decode(base64_string);  
var byteArray = Base64Binary.decodeArrayBuffer(base64_string); 

1
이 방법은 atob을 사용하는 것보다 2 배 빠릅니다.
xiaoyu2er dec.

4
작동하지 않는 예를 들어 줄 수 있습니까? 이 기사에서는 유니 코드 문자를 포함 할 수 있지만 전혀 적용되지 않는 임의의 문자열 인코딩에 대해 설명 atob합니다.
형이

1
decodeArrayBufferArrayBuffer항상 3으로 나눌 수있는 크기를 가진을 반환합니다 . 디자인에 의한 것인지 버그인지 이해할 수 없습니다. github 프로젝트에서 물어볼 것입니다.
ceztko

@ceztko 아마도 (우연한) 디자인 때문일 것입니다. base64 인코딩 알고리즘은 3 바이트 그룹을 4 문자로 변환합니다. 디코드 메소드는 길이가 base64String.length / 4 * 3 바이트 인 ArrayBuffer를 할당하고 완료시 사용되지 않은 바이트를 자르지 않습니다.
AlwaysLearning 2011

1
@AlwaysLearning은 남은 0 바이트가 의도 한 출력 콘텐츠를 손상시킬 수 있기 때문에 버그가있을 수 있음을 의미합니다.
ceztko 2011


9

비동기 솔루션, 데이터가 때 더 좋습니다.

// 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);
}

6

Javascript는 훌륭한 개발 환경이므로이 작은 문제에 대한 해결책을 제공하지 않는 것보다 이상하게 보입니다. 이 페이지의 다른 곳에서 제공되는 솔루션은 잠재적으로 느립니다. 여기 내 해결책이 있습니다. base64 이미지 및 사운드 데이터 URL을 디코딩하는 내장 기능을 사용합니다.

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();

기본 65 문자열의 형식이 잘못된 경우 전송 요청이 실패합니다.

MIME 유형 (애플리케이션 / 옥텟)은 아마도 불필요 할 것입니다.

크롬에서 테스트되었습니다. 다른 브라우저에서도 작동합니다.


1
이것은 간단하고 깨끗한 저에게 완벽한 솔루션이었습니다. Firefox, IE 11, Edge에서 빠르게 테스트했으며 잘 작동했습니다!
cs-NET

원래의 질문에 관련되지 않습니다
제임스 뉴턴에게

IE11에서 어떻게 작동하는지 잘 모르겠지만 Access DeniedCORS 제한으로 보이는 오류가 발생합니다.
Sergiu

6

Node.js 사용자의 경우 :

const myBuffer = Buffer.from(someBase64String, 'base64');

myBuffer는 Uint8Array의 하위 클래스 인 Buffer 유형입니다. 불행히도 Uint8Array는 OP가 요청한대로 ArrayBuffer가 아닙니다. 그러나 ArrayBuffer를 조작 할 때 거의 항상 Uint8Array 또는 이와 유사한 것으로 래핑하므로 요청되는 내용에 가까워 야합니다.


2

순수 JS-문자열 중간 단계 없음 (atob 없음)

나는 base64를 직접적인 방식으로 (중간에서 문자열로 변환하지 않고) 변환하는 다음 함수를 작성합니다. 생각

  • 4 base64 문자 청크 얻기
  • base64 알파벳으로 각 문자의 색인 찾기
  • 인덱스를 6 비트 숫자 (이진 문자열)로 변환
  • 24 비트 숫자 (이진 문자열로 저장 됨)를 제공하는 4 개의 6 비트 숫자 결합
  • 24 비트 문자열을 3 개의 8 비트로 분할하고 각각을 숫자로 변환하여 출력 배열에 저장합니다.
  • 코너 케이스 : 입력 base64 문자열이 1/2 =문자로 끝나면 출력 배열에서 1/2 숫자를 제거합니다.

아래 솔루션은 큰 입력 base64 문자열을 처리 할 수 ​​있습니다. btoa이없이 변환에 대한 유사 기능은베이스 64에 바이트 여기


그래서 누락 된 "."?
Gillsoft AB

브라우저에서 테스트했는데 이것이 예상 된 결과인지 확실하지 않습니까? "이상한 나라의 앨리스 모험"(즉, 마지막 캐릭터는 NaN)
Gillsoft AB

1
@GillsoftAB이 정보에 감사드립니다-당신이 옳습니다-나는 문제를 해결합니다
Kamil Kiełczewski

-3
const str = "dGhpcyBpcyBiYXNlNjQgc3RyaW5n"
const encoded = new TextEncoder().encode(str) // is Uint8Array
const buf = encoded.buffer // is ArrayBuffer

6
이것은 Base64 디코딩 / 인코딩을 수행하지 않습니다. "base64"의 6 바이트를 6 요소 ArrayBuffer 또는 Uint8Array로 변환합니다.
dubek

2
@dubek 그게 질문받은 것입니다.
Andrii Nemchenko
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.