如何将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建议),由于验证/变量准备/条件处理的数量很大,这可能是杂乱的/不可能的在提交表单之前进行.
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 /等待:
$(document).on("click", ".clicker", async function() {
var promise = getBase64(my_pdf_file);
var my_pdf_file_as_base64 = await promise;
}
(请注意,await
仅在async
函数中起作用,因此您的点击处理程序必须为async
.我还尝试添加一个繁忙的等待循环,但这导致浏览器挂起.)
This prints base64 out to console:
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
Source: https://stackoverflow.com/a/36281449/1063287
jsFiddle: jsFiddle demo of the above working code
I want to be able to assign the base64 to a variable, so I tried the following, based on 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);
It is currently printing nothing out to the console.
Question:
How can I save the base64 value as a variable?
Edit:
As requested, for context:
I am submitting a form in a Google Apps Script environment.
I have done this previously and passed a form object (which included a file) through to the Google Apps Script function.
However, one of the constraints of this approach is that if passing a form object as a parameter, it is the only parameter allowed.
A form element within the page is also legal as a parameter, but it must be the function’s only parameter
In this instance, I am passing multiple parameters through, and one of the parameters will be a pdf file, converted to base64.
In response to @Aasmund's great answer, I would like the variable assignment to block further code execution:
var my_pdf_file = [ converted file here ];
// don't do this stuff until the above variable is assigned
Otherwise, I will have to refactor the remaining code to take place in the then
block (suggested by @Aasmund), and that might be messy / impossible due to the amount of validation / variable preparation / conditional handling that is taking place before the form is submitted.
FileReader.readAsDataURL()
is asynchronous - the download happens in the background while the rest of the code keeps executing. So the reason console.log(my_pdf_file_as_base64);
prints an empty string is that the line my_pdf_file_as_base64 = e.target.result
hasn't been executed yet: the call to getBase64()
finishes almost immediately, and the subsequent statement is executed; only later (when the download is complete) will the callback be executed.
The way to handle this is to place the code that uses the downloaded file inside the callback:
getBase64(my_pdf_file, function(e) {
my_pdf_file_as_base64 = e.target.result;
console.log(my_pdf_file_as_base64);
});
Alternatively, you can repeatedly (e.g. inside a setTimeout
callback or inside some DOM event handler) check if reader.readyState === FileReader.DONE
- whenever this becomes true, reader.result
will contain the file.
A more flexible approach is to use a Promise
, which is an object that encapsulates an asynchronous computation:
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);
});
So far, this looks pretty similar to the first solution, but the advantage is that promise
is an object that you can pass around to other functions, so that you can start a computation in one place and decide in another place what should happen when it's finished.
As you have probably noticed, neither of these approaches allow you to block further code execution until the file content has been assigned to the global variable my_pdf_file_as_base64
. This is by design; however, if you really really need to block on the download because you don't have time to refactor old code, see the discussion in https://stackoverflow.com/a/39914235/626853. If your user's browsers are sufficiently modern, you can use async/await:
$(document).on("click", ".clicker", async function() {
var promise = getBase64(my_pdf_file);
var my_pdf_file_as_base64 = await promise;
}
(Note that await
only works inside async
functions, so your click handler must be async
. I also experimented with adding a busy waiting loop, but that caused my browser to hang.)
这篇关于如何将FileReader base64捕获为变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!