将二进制文件转换为 JavaScript 字符串,然后转换为 Uint8Array
Convert binary file to JavaScript string and then to Uint8Array
我正在尝试创建一个可以通过 file://
URI 使用的 Web 应用程序。这意味着我不能使用 AJAX 加载二进制文件(不关闭浏览器中的安全功能,原则上我不想这样做)。
该应用程序使用 SQLite 数据库。我想将数据库提供给 sql.js 构造函数,它需要 Uint8Array
格式。
因为我不能使用 AJAX 加载数据库文件,我可以改为使用 <input type="file">
和 FileReader.prototype.readAsArrayBuffer
加载它,并将 ArrayBuffer
转换为 Uint8Array
。这适用于以下代码:
input.addEventListener('change', function (changeEvent) {
var file = changeEvent.currentTarget.files[0];
var reader = new FileReader();
reader.addEventListener('load', function (loadEvent) {
var buffer = loadEvent.target.result;
var uint8Array = new Uint8Array(buffer);
var db = new sql.Database(uint8Array);
});
reader.readAsArrayBuffer(file);
});
但是,<input type="file">
需要用户交互,这很乏味。
我想我可以通过使用构建工具将我的数据库文件转换为 JavaScript 对象/字符串并生成“.js”来解决 no-AJAX 限制提供文件内容的文件,然后以某种方式将文件内容转换为Uint8Array
。
伪代码:
// In Node.js:
var fs = require('fs');
var sqliteDb = fs.readFileSync('path/to/sqlite.db');
var string = convertBufferToJsStringSomehow(sqliteDb);
fs.writeFileSync('build/db.js', 'var dbString = "' + string + '";');
// In the browser (assume "build/db.js" has been loaded via a <script> tag):
var uint8Array = convertStringToUint8ArraySomehow(dbString);
var db = new sql.Database(uint8Array);
在 Node.js 中,我尝试了以下方法:
var TextEncoder = require('text-encoding').TextEncoder;
var TextDecoder = require('text-encoding').TextEncoder;
var sql = require('sql.js');
var string = new TextDecoder('utf-8').decode(fs.readFileSync('path/to/sqlite.db'));
// At this point, I would write `string` to a ".js" file, but for
// the sake of determining if converting back to a Uint8Array
// would work, I'll continue in Node.js...
var uint8array = new TextEncoder().encode(string);
var db = new sql.Database(uint8array);
db.exec('SELECT * FROM tablename');
但是当我这样做时,出现错误 "Error: database disk image is malformed"。
我做错了什么?这可能吗?当我通过 FileReader
.
加载相同文件时,数据库磁盘映像不是 "malformed"
And that's working with the following code:
input.addEventListener('change', function (changeEvent) {
var file = changeEvent.currentTarget.files[0];
var reader = new FileReader();
reader.addEventListener('load', function (loadEvent) {
var buffer = loadEvent.target.result;
var uint8Array = new Uint8Array(buffer);
var db = new sql.Database(uint8Array);
});
reader.readAsArrayBuffer(file);
});
However, <input type="file">
requires user interaction, which is
tedious.
使用当前的工作方法比尝试创建解决方法要简单得多。如果用户打算使用应用程序,用户可以从他们的文件系统 select 文件到 运行 应用程序。
使用以下代码,我能够将数据库文件的内容传输到浏览器:
// In Node.js:
var fs = require('fs');
var base64 = fs.readFileSync('path/to/sqlite.db', 'base64');
fs.writeFileSync('build/db.js', 'var dbString = "' + base64 + '";');
// In the browser (assume "build/db.js" has been loaded via a <script> tag):
function base64ToUint8Array (string) {
var raw = atob(string);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));
for (var i = 0; i < rawLength; i += 1) {
array[i] = raw.charCodeAt(i);
}
return array;
}
var db = new sql.Database(base64ToUint8Array(dbString));
console.log(db.exec('SELECT * FROM tablename'));
我正在尝试创建一个可以通过 file://
URI 使用的 Web 应用程序。这意味着我不能使用 AJAX 加载二进制文件(不关闭浏览器中的安全功能,原则上我不想这样做)。
该应用程序使用 SQLite 数据库。我想将数据库提供给 sql.js 构造函数,它需要 Uint8Array
格式。
因为我不能使用 AJAX 加载数据库文件,我可以改为使用 <input type="file">
和 FileReader.prototype.readAsArrayBuffer
加载它,并将 ArrayBuffer
转换为 Uint8Array
。这适用于以下代码:
input.addEventListener('change', function (changeEvent) {
var file = changeEvent.currentTarget.files[0];
var reader = new FileReader();
reader.addEventListener('load', function (loadEvent) {
var buffer = loadEvent.target.result;
var uint8Array = new Uint8Array(buffer);
var db = new sql.Database(uint8Array);
});
reader.readAsArrayBuffer(file);
});
但是,<input type="file">
需要用户交互,这很乏味。
我想我可以通过使用构建工具将我的数据库文件转换为 JavaScript 对象/字符串并生成“.js”来解决 no-AJAX 限制提供文件内容的文件,然后以某种方式将文件内容转换为Uint8Array
。
伪代码:
// In Node.js:
var fs = require('fs');
var sqliteDb = fs.readFileSync('path/to/sqlite.db');
var string = convertBufferToJsStringSomehow(sqliteDb);
fs.writeFileSync('build/db.js', 'var dbString = "' + string + '";');
// In the browser (assume "build/db.js" has been loaded via a <script> tag):
var uint8Array = convertStringToUint8ArraySomehow(dbString);
var db = new sql.Database(uint8Array);
在 Node.js 中,我尝试了以下方法:
var TextEncoder = require('text-encoding').TextEncoder;
var TextDecoder = require('text-encoding').TextEncoder;
var sql = require('sql.js');
var string = new TextDecoder('utf-8').decode(fs.readFileSync('path/to/sqlite.db'));
// At this point, I would write `string` to a ".js" file, but for
// the sake of determining if converting back to a Uint8Array
// would work, I'll continue in Node.js...
var uint8array = new TextEncoder().encode(string);
var db = new sql.Database(uint8array);
db.exec('SELECT * FROM tablename');
但是当我这样做时,出现错误 "Error: database disk image is malformed"。
我做错了什么?这可能吗?当我通过 FileReader
.
And that's working with the following code:
input.addEventListener('change', function (changeEvent) { var file = changeEvent.currentTarget.files[0]; var reader = new FileReader(); reader.addEventListener('load', function (loadEvent) { var buffer = loadEvent.target.result; var uint8Array = new Uint8Array(buffer); var db = new sql.Database(uint8Array); }); reader.readAsArrayBuffer(file); });
However,
<input type="file">
requires user interaction, which is tedious.
使用当前的工作方法比尝试创建解决方法要简单得多。如果用户打算使用应用程序,用户可以从他们的文件系统 select 文件到 运行 应用程序。
使用以下代码,我能够将数据库文件的内容传输到浏览器:
// In Node.js:
var fs = require('fs');
var base64 = fs.readFileSync('path/to/sqlite.db', 'base64');
fs.writeFileSync('build/db.js', 'var dbString = "' + base64 + '";');
// In the browser (assume "build/db.js" has been loaded via a <script> tag):
function base64ToUint8Array (string) {
var raw = atob(string);
var rawLength = raw.length;
var array = new Uint8Array(new ArrayBuffer(rawLength));
for (var i = 0; i < rawLength; i += 1) {
array[i] = raw.charCodeAt(i);
}
return array;
}
var db = new sql.Database(base64ToUint8Array(dbString));
console.log(db.exec('SELECT * FROM tablename'));