JQuery $. Получать и раздувать данные
Мне передали небольшое браузерное приложение, которое извлекает двоичный файл, распаковывает его и затем показывает его содержимое в браузере.
Однако я не могу правильно преобразовать данные в байтовый массив, и впоследствии инфляция завершается неудачно с "недопустимой длиной кода".
Это мой метод get:
$.get("metafile.hsm", function (metaFile) {
readCellFile(metaFile);
});
И это метод раздувания файла:
function readCellFile(file) {
var reader = new FileReader();
// var file = document.getElementById('cell_file_input').files[0];
reader.onload = function() {
var compressedData = new Uint8Array(reader.result);
var data = pako.inflate(compressedData); // Error "Invalid code length set"
var buf = new flatbuffers.ByteBuffer(data);
var cell = hdm.storage.hsg.Cell.getRootAsCell(buf);
var features = parseCell(cell);
// ...
}
reader.onerror = function(event) {
console.error("File could not be read! Code " + event.target.error.code);
};
var blob = new Blob([file], {type: "application/octet-stream"});
reader.readAsArrayBuffer(blob);
}
Я делаю преобразование неправильно? Я могу исключить, что файл поврежден, как вы можете видеть в закомментированной строке, которую я тестировал, чтобы загрузить файл, и он работал.
1 ответ
Прежде всего вы должны проверить, действительно ли gzipping в Javascript необходим для вашей цели. Если сервер настроен на поддержку файлов gzip, а браузер поддерживает gzip, то файлы (даже те, которые запрашиваются через javascript) должны автоматически сжиматься.
Если вам нужно использовать этот подход (например, потому что вы не имеете никакого контроля над сервером), то, вероятно, лучше извлечь файл из веб-работника и также выполнить разархивирование. В следующем коде (протестированном для работы с Chrome с текстовым файлом в формате gzip) предполагается, что файл pako_inflate.min.js находится в том же каталоге, что и основной сценарий и рабочий. Также обратите внимание, что при локальном тестировании ваш браузер может заблокировать загрузку веб-работника из локального файла по соображениям безопасности.
Просто вызовите loadFile, передав имя файла, который вы хотите загрузить. onFileLoaded будет вызываться с данными после завершения загрузки.
fileLoader.js
/*
* If you are running this locally your browser may block you from
* loading web worker from a local file. For testing you may want to run
* a simple local web server like so: 'python -m http.server 8000'
*/
var gzippedFileLoaderWorker = new Worker("gzippedFileLoaderWorker.js");
gzippedFileLoaderWorker.onmessage = function (event) {
var message = event.data;
if (message.type == "START") {
console.log(message.data);
} else if (message.type == "END") {
onFileLoaded(message.data);
} else if (message.type == "ERROR") {
console.log(message.data);
}
};
function loadFile(fileName) {
gzippedFileLoaderWorker.postMessage({
type: 'loadFile',
fileName: fileName
});
}
function onFileLoaded(uncompressedFileData) {
console.log("Data Loaded:" + uncompressedFileData);
}
gzippedFileLoaderWorker.js
importScripts('pako_inflate.min.js');
onmessage = function(event) {
var message = event.data;
if (message.type === "loadFile") {
postMessage({
'type' : 'START',
'data' : "Started Downloading: " + message.fileName
});
try {
/*
* Fetch is not supported on ie yet. If this is a requirement
* find a polyfill like whatwg-fetch
*/
fetch(message.fileName).then(function(response) {
if (!response["ok"]) {
postMessage({
'type' : 'ERROR',
'data' : "Error loading: " + message.fileName
})
}
return response["arrayBuffer"]();
}).then(function(zipped) {
return pako.ungzip(new Uint8Array(zipped));
}).then(function(binary) {
/*
* Do any processing on the binary data here so you don't
* block the main thread! Then pass that data back as an
* object instead of the binary in the post message
*/
postMessage({
'type' : 'END',
'data' : binary
});
});
} catch(err) {
postMessage({
'type' : 'ERROR',
'data' : err.message
});
}
}
}