簡體   English   中英

如何將 FileReader base64 捕獲為變量?

[英]How to capture FileReader base64 as variable?

這會將 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演示

我希望能夠將 base64 分配給一個變量,所以我根據這個答案嘗試了以下操作:

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 腳本函數。

但是,這種方法的一個限制是,如果將表單對象作為參數傳遞,則它是唯一允許的參數。

頁面中的表單元素作為參數也是合法的,但它必須是函數的唯一參數

來源

在這個例子中,我傳遞了多個參數,其中一個參數是一個 pdf 文件,轉換為 base64。

為了回應@Aasmund 的精彩回答,我希望變量賦值能夠阻止進一步的代碼執行:

var my_pdf_file = [ converted file here ];

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

否則,我將不得不重構剩余的代碼以在then塊中發生(由@Aasmund 建議),並且由於在表單之前發生的驗證/變量准備/條件處理的數量,這可能是混亂的/不可能的被提交。

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

到目前為止,這看起來與第一個解決方案非常相似,但優點是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;
}

(請注意, await僅在async函數內有效,因此您的點擊處理程序必須是async 。我還嘗試添加一個繁忙的等待循環,但這導致我的瀏覽器掛起。)

我按此守則工作

   async function checkFileBase64(el) {
        let inputEl = $(el).find('input[type=file]');
        let promise = getBase64(inputEl[0]);
        return await promise;
    }
    function getBase64(file) {
       return new Promise(function (resolve, reject) {
            let reader = new FileReader();
            reader.onload = function () { resolve(reader.result); };
            reader.onerror = reject;
            reader.readAsDataURL(file.files[0]);
        });
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM