读取 javascript 中的本地二进制文件并转换为 base64
Reading a local binary file in javascript and converting to base64
我有一个 local 站点,它使用 Javascript 浏览我机器上的文件。这不是 NodeJS 问题。我一直在读取本地文件系统上的 binary 文件并将它们转换为 base64。我遇到的问题是有不可打印的字符。我从 javascript 获得的输出与 Linux 中的 base64
命令行工具不同。
一个示例文件,我们可以用于这个问题,是用 head -c 8 /dev/random > random
生成的——它只是一些写入文件的二进制废话。在此示例中,它产生了以下内容:
$ base64 random
Tg8j3hAv/u4=
如果您想在家一起玩,可以运行生成相同的文件:
echo -n 'Tg8j3hAv/u4=' | base64 -d > random
但是,当我尝试在 Javascript 中读取该文件并将其转换为 base64 时,我得到了不同的结果:
Tg8j77+9EC/vv73vv70=
看起来有点相似,但是里面有一些其他的字符。
我是这样得到它的:
function readTextFile(file)
{
let fileContents;
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
fileContents = rawFile.responseText;
}
}
}
rawFile.send(null);
return fileContents;
}
var fileContents = readTextFile("file:///Users/henrytk/tmp/stuff/random");
console.log(btoa(unescape(encodeURIComponent(fileContents))));
// I also tried
console.log(Base64.encode(fileContents));
// from http://www.webtoolkit.info/javascript_base64.html#.YVW4WaDTW_w
// but I got the same result
这是怎么回事?这与我阅读文件的方式有关吗?我希望能够以 运行 本地 的方式同步读取该文件 - 没有 NodeJS,没有花哨的第三方库,如果可能的话。
我认为这是问题所在:
fileContents = rawFile.responseText
这会将您的文件读取为 JavaScript 字符串,并非所有二进制文件都是有效的 JavaScript 字符代码点。
我会推荐使用 fetch 来获取 blob,因为这是我最了解的方法:
async function readTextFileAsBlob(file) {
const response = await fetch( file );
const blob = await response.blob();
return blob;
}
然后,使用浏览器的 FileReader 将 blob 转换为 base64。
(也许与 Linux 工具匹配?)
const blobToBase64DataURL = blob => new Promise(
resolvePromise => {
const reader = new FileReader();
reader.onload = () => resolvePromise( reader.result );
reader.readAsDataURL( blob );
}
);
在您的示例中,您将像这样使用这些函数:
readTextFileAsBlob( "file:///Users/henrytk/tmp/stuff/random" ).then(
async blob => {
const base64URL = await blobToBase64DataURL( blob );
console.log( base64URL );
}
);
这会给你一个 URL 就像 data://...
。您需要拆分 URL 部分,但如果一切顺利,最后一位应该是正确的 base64 数据。 (希望如此)。
我有一个 local 站点,它使用 Javascript 浏览我机器上的文件。这不是 NodeJS 问题。我一直在读取本地文件系统上的 binary 文件并将它们转换为 base64。我遇到的问题是有不可打印的字符。我从 javascript 获得的输出与 Linux 中的 base64
命令行工具不同。
一个示例文件,我们可以用于这个问题,是用 head -c 8 /dev/random > random
生成的——它只是一些写入文件的二进制废话。在此示例中,它产生了以下内容:
$ base64 random
Tg8j3hAv/u4=
如果您想在家一起玩,可以运行生成相同的文件:
echo -n 'Tg8j3hAv/u4=' | base64 -d > random
但是,当我尝试在 Javascript 中读取该文件并将其转换为 base64 时,我得到了不同的结果:
Tg8j77+9EC/vv73vv70=
看起来有点相似,但是里面有一些其他的字符。
我是这样得到它的:
function readTextFile(file)
{
let fileContents;
var rawFile = new XMLHttpRequest();
rawFile.open("GET", file, false);
rawFile.onreadystatechange = function ()
{
if(rawFile.readyState === 4)
{
if(rawFile.status === 200 || rawFile.status == 0)
{
fileContents = rawFile.responseText;
}
}
}
rawFile.send(null);
return fileContents;
}
var fileContents = readTextFile("file:///Users/henrytk/tmp/stuff/random");
console.log(btoa(unescape(encodeURIComponent(fileContents))));
// I also tried
console.log(Base64.encode(fileContents));
// from http://www.webtoolkit.info/javascript_base64.html#.YVW4WaDTW_w
// but I got the same result
这是怎么回事?这与我阅读文件的方式有关吗?我希望能够以 运行 本地 的方式同步读取该文件 - 没有 NodeJS,没有花哨的第三方库,如果可能的话。
我认为这是问题所在:
fileContents = rawFile.responseText
这会将您的文件读取为 JavaScript 字符串,并非所有二进制文件都是有效的 JavaScript 字符代码点。
我会推荐使用 fetch 来获取 blob,因为这是我最了解的方法:
async function readTextFileAsBlob(file) {
const response = await fetch( file );
const blob = await response.blob();
return blob;
}
然后,使用浏览器的 FileReader 将 blob 转换为 base64。
(也许与 Linux 工具匹配?)
const blobToBase64DataURL = blob => new Promise(
resolvePromise => {
const reader = new FileReader();
reader.onload = () => resolvePromise( reader.result );
reader.readAsDataURL( blob );
}
);
在您的示例中,您将像这样使用这些函数:
readTextFileAsBlob( "file:///Users/henrytk/tmp/stuff/random" ).then(
async blob => {
const base64URL = await blobToBase64DataURL( blob );
console.log( base64URL );
}
);
这会给你一个 URL 就像 data://...
。您需要拆分 URL 部分,但如果一切顺利,最后一位应该是正确的 base64 数据。 (希望如此)。