base64文字列をArrayBufferに変換します


98

base64エンコード文字列をArrayBufferに変換する必要があります。base64文字列はユーザ​​ー入力であり、メールからコピーアンドペーストされるため、ページが読み込まれたときに文字列は表示されません。可能であればサーバーにajax呼び出しを行わずに、JavaScriptでこれを実行したいと思います。

これらのリンクは興味深いものでしたが、役に立ちませんでした。

ArrayBufferからbase64でエンコードされた文字列

これは、逆の変換ではなく、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
ここで実際に何が起こっているのか説明してください。
Govi S

4
まあ、それはかなり単純です。最初にbase64文字列(atob)をデコードし、次に、デコードされた文字列と同じ長さの8ビット符号なし整数の新しい配列を作成します。その後、文字列を反復処理し、文字列の各文字のUnicode値を配列に入力します。
Goran.it 2016年

2
MDNから:Base64は、バイナリデータを基数64表現に変換することにより、ASCII文字列形式でバイナリデータを表す、類似したバイナリからテキストへのエンコードスキームのグループです。Uint8Arrayアレイは8ビット符号なし整数の配列を表し、そして我々は(また、8ビットのテーブルである)データのASCII表現..で作業している型付き
Goran.it

3
これは正しくありません。これにより、javascriptがバイトを文字列として解釈できるようになり、実際には真のバイナリであるデータに影響します。
トマーシュZato -復活モニカ

4
問題は、Unicodeのすべての文字は1バイトであるそうではない))ではないすべてのバイトシーケンスが有効なUnicode Bであるということですbytes[i] = binary_string.charCodeAt(i);間違っている可能性が
混合物

52

TypedArray.fromの使用:

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

Goran.it回答のforループバージョンと比較するパフォーマンス。


2
この種の1つのライナーが好きな人にとってはUint8Array.from、一部のブラウザーとの互換性がまだほとんどないことに注意してください。
IzumiSy 2017

2
:ATOBかbtoaお勧めしないでくださいdeveloper.mozilla.org/en-US/docs/Web/API/WindowBase64/...
クーゲル

Railsコンパイラはこの文字列を処理できず、で失敗しExecJS::RuntimeError: SyntaxError: Unexpected token: operator (>)ます。(レール5)
Avael Kross 2017

3
これは配列バッファではありません。これは型付き配列です。.bufferから返されるもののプロパティを通じて配列バッファーにアクセスできますUint8Array
オリゴフレン2018

4
@Saites、atoborにbtoaは何も問題はありません。有効な入力を与えるだけです。atob有効なbase64文字列が必要です。それ以外の場合はエラーがスローされます。またbtoa、0〜255の範囲の文字を含む文字列である有効なバイト文字列(バイナリ文字列とも呼ばれる)が必要です。文字列にその範囲外の文字が含まれている場合btoa、エラーがスローされます。
GetFree

34

- Goran.itの答えはあるため、JavaScriptでのUnicodeの問題では動作しません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 2017

4
それが機能しない例を挙げていただけますか?この記事では、Unicode文字を含む可能性のある任意の文字列のエンコードについて説明していますがatob、まったく該当しません。
riv

1
decodeArrayBufferArrayBuffer常に3で割り切れるサイズのを返します。これが仕様によるものかバグによるものかはわかりません。私はgithubプロジェクトで尋ねます。
ceztko

@ceztkoそれはおそらく(偶然の)設計によるものです。base64エンコードアルゴリズムは3バイトのグループを取り、それらを4文字に変換します。デコードメソッドは、おそらく長さがbase64String.length / 4 * 3バイトのArrayBufferを割り当て、終了時に未使用のバイトを切り捨てることはありません。
AlwaysLearning、

1
@AlwaysLearningは、残りのゼロバイトが意図した出力コンテンツを破損する可能性があるため、おそらくバグがあることを意味します。
ceztko

21

先月(2017-08)、信じられないほど高い使用率の500万ダウンロードの小さなnpmパッケージ、base64-arraybufferが見つかりました。

https://www.npmjs.com/package/base64-arraybuffer

最高の標準ソリューションの何かを探している人にとって、これはそれかもしれません。


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

元の質問とは関係ありません
James Newton

IE11でどのように機能するかはわかりませんAccess Deniedが、CORSの制限のように思われるエラーが表示されます。
セルジュ

6

Node.jsユーザーの場合:

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

myBufferは、Uint8ArrayのサブクラスであるタイプBufferになります。残念ながら、OPが要求していたUint8ArrayはArrayBufferではありません。しかし、ArrayBufferを操作するときは、ほとんどの場合、Uint8Arrayまたは同様の何かでラップするので、要求されているものに近いはずです。


2

純粋なJS-文字列の中間ステップなし(atobなし)

base64を直接変換する次の関数を記述します(途中で文字列に変換せずに)。考え

  • 4つのbase64文字チャンクを取得します
  • base64アルファベットで各文字のインデックスを見つける
  • インデックスを6ビットの数値(バイナリ文字列)に変換します
  • 24ビットの数値を与える4つの6ビット数値を結合します(バイナリ文字列として格納されます)
  • 24ビット文字列を3つの8ビットに分割し、それぞれを数値に変換して、出力配列に格納する
  • コーナーケース:入力base64文字列が1/2文字で終わる=場合、出力配列から1/2の数値を削除します

以下のソリューションでは、大きな入力base64文字列を処理できます。バイトをbtoaなしでbase64に変換するための同様の関数はこちら


「。」の欠落はありませんか?
Gillsoft AB

ブラウザでテストします。これが期待どおりの結果かどうかはわかりません。「不思議の国のアリスの冒険」(つまり、最後のキャラクターはNaNです)
Gillsoft AB

1
@GillsoftABこの情報をありがとう-あなたは正しい-私は問題を修正します
KamilKieł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に変換するだけです。
2018年

2
@dubekそれが求められているものです。
Andrii Nemchenko
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.