2017-11-09 26 views
0

これは、コンソールに出BASE64を出力します。変数としてFileReader base64をキャプチャする方法は?

function getBase64(file) { 
    var reader = new FileReader(); 
    reader.readAsDataURL(file); 
    reader.onload = function() { 
     console.log(reader.result); 
    }; 
    reader.onerror = function(error) { 
     console.log('Error: ', error); 
    }; 
} 

var file = document.querySelector('#files > input[type="file"]').files[0]; 
getBase64(file); // prints the base64 string 

出典:https://stackoverflow.com/a/36281449/1063287

jsFiddle:jsFiddle demo of the above working code

私は変数にBASE64を割り当てることができるようにしたいので、私が試しましたthis answerに基づく以下:

function getBase64(file, onLoadCallback) { 
    var reader = new FileReader(); 
    reader.readAsDataURL(file); 
    reader.onload = onLoadCallback; 
    reader.onerror = function(error) { 
     console.log('Error when converting PDF file to base64: ', error); 
    }; 
} 

var my_pdf_file = document.querySelector("#my_pdf_file").files[0]; 
var my_pdf_file_as_base64 = ""; 
getBase64(my_pdf_file, function(e) { 
    my_pdf_file_as_base64 = e.target.result 
}); 

// print out the base64 to show i have captured the value correctly 
console.log(my_pdf_file_as_base64); 

現在、コンソールに何も印刷していません。

質問:

私は変数としてbase64で値を保存することができますどのように?

編集:

コンテキストのために、要求されたよう:

私には、Google Appsスクリプト環境でフォームを送信しています。

私は以前これを行い、フォームオブジェクト(ファイルを含む)をGoogle Apps Script関数に渡しました。

しかし、このアプローチの制約の1つは、フォームオブジェクトをパラメータとして渡す場合、これが唯一のパラメータであるということです。ページ内

フォーム要素は、パラメータとして有効ですが、それは は、関数のパラメータのみ、このインスタンスで

Source

でなければならない、私は、複数のパラメータを通過していますパラメータの1つがpdfファイルになり、base64に変換されます。 Aasmundの偉大な答えは@に対応して

、私はさらに、コード実行ブロックする変数割り当てたい:

var my_pdf_file = [ converted file here ]; 

// don't do this stuff until the above variable is assigned 

をそうでなければ、私はthenブロックに場所を取るために、残りのコードをリファクタリングする必要があります(提案by @Aasmund)、それはフォームが提出される前に行われているバリデーション/変数準備/条件付き処理のために乱雑/不可能かもしれません。残りのコードが実行し続けながらダウンロードはバックグラウンドで行わ -

答えて

4

FileReader.readAsDataURL()非同期です。したがって、console.log(my_pdf_file_as_base64);が空文字列を出力する理由は、my_pdf_file_as_base64 = e.target.result行がまだ実行されていないことです。getBase64()への呼び出しがほぼ直ちに終了し、後続の文が実行されます。後で(ダウンロードが完了すると)コールバックが実行されます。

これを処理する方法は内でコールバックダウンロードしたファイルを使用するコード配置することです:あなたが繰り返しでき、また

getBase64(my_pdf_file, function(e) { 
    my_pdf_file_as_base64 = e.target.result; 
    console.log(my_pdf_file_as_base64); 
}); 

を(例えばsetTimeoutコールバックの内側またはいくつかのDOMイベントハンドラ内) reader.readyState === FileReader.DONEをチェックします。これが真になるときは、reader.resultにファイルが含まれます。

より柔軟なアプローチは、非同期計算をカプセル化するオブジェクトである、Promiseを使用することです:

function getBase64(file, onLoadCallback) { 
    return new Promise(function(resolve, reject) { 
     var reader = new FileReader(); 
     reader.onload = function() { resolve(reader.result); }; 
     reader.onerror = reject; 
     reader.readAsDataURL(file); 
    }); 
} 

var promise = getBase64(my_pdf_file); 
promise.then(function(result) { 
    console.log(result); 
}); 

はこれまでのところ、これが第1の溶液にかなり似ていますが、利点がpromiseがあるということです他の関数に渡すことができるオブジェクトであるため、ある場所で計算を開始し、終了時に何が起こるべきかを別の場所で決めることができます。

おそらく気づいたように、これらのアプローチでは、ファイル内容がグローバル変数my_pdf_file_as_base64に割り当てられるまで、コードの実行をブロックすることはできません。これは設計によるものです。ただし、古いコードをリファクタリングする時間がないため、実際にダウンロードをブロックする必要がある場合は、https://stackoverflow.com/a/39914235/626853のディスカッションを参照してください。ユーザーのブラウザが十分に近代的であれば、あなたはasync/awaitを使用することができます。

$(document).on("click", ".clicker", async function() { 
    var promise = getBase64(my_pdf_file); 
    var my_pdf_file_as_base64 = await promise; 
} 

あなたのクリックハンドラはasyncでなければならないので(、awaitは内側のみasync機能を動作することに注意してください、私も忙しい待機ループを追加することで実験し、。それが原因でブラウザがハングアップすることがありました)。

+0

元の投稿に文脈を追加しました。ありがとうございます。 – user1063287

+0

@ user1063287:私の更新を参照してください。 –

+0

オンクリックハンドラは、実際のインスタンスがフォーム検証ライブラリのsuccessハンドラで実行されるように、サンプル動作を促すためにデモで表示されましたが、非同期ではないと仮定しています。 FileReader base64の同期割り当てが可能な場合、将来の誰かが投稿を見ている場合は、私たちにお知らせください!ありがとう! – user1063287

関連する問題