这会将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脚本功能。
但是,这种方法的一个限制是,如果将表单对象作为参数传递,则它是唯一允许的参数。
页面中的表单元素也是合法的参数,但它 必须是函数的唯一参数
在这个例子中,我传递了多个参数,其中一个参数将是一个pdf文件,转换为base64。
为了回应@ Aasmund的好答案,我希望变量赋值可以阻止进一步的代码执行:
var my_pdf_file = [ converted file here ];
// don't do this stuff until the above variable is assigned
否则,我将不得不重构剩余的代码,发生在then
块(由@Aasmund建议),由于验证/变量准备/条件处理的数量,这可能是混乱/不可能的在提交表单之前发生的事情。
答案 0 :(得分:15)
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
。我还尝试添加繁忙的等待循环,但这导致我的浏览器挂起。)
答案 1 :(得分:0)
我按此守则工作
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]);
});
}