kopia lustrzana https://github.com/viljoviitanen/js-untar
Added buffer to file. Added installation and better usage instructions.
rodzic
b2edee96ad
commit
487a977047
|
@ -1,2 +1 @@
|
|||
build
|
||||
node_modules
|
||||
|
|
53
README.md
53
README.md
|
@ -11,38 +11,40 @@ Useful when packing all your application images/sound/json/etc. data in a standa
|
|||
As of September 2015 this includes Chrome>=20, Firefox>=13, IE>=10, Opera>=12.10 and Safari>=8.
|
||||
[Web Worker transferable objects](https://developer.mozilla.org/en-US/docs/Web/API/Worker/postMessage) are used when available, increasing speed greatly. This is supported in Chrome>=21, Firefox>=18, Opera>=15 and Safari.
|
||||
|
||||
## Installation
|
||||
bower install --save js-untar
|
||||
|
||||
## Documentation
|
||||
Load the module with RequireJS or similar. The module is a function that returns a modified Promise with a progress callback.
|
||||
Supports AMD, CommonJS or simply load with a script tag, which will provide a global untar function.
|
||||
The module is a function that returns a modified Promise with a progress callback.
|
||||
This callback is executed every time a file is extracted.
|
||||
The standard Promise.then method is also called when extraction is done, with all extracted files as argument.
|
||||
The extraction is done in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) to allow the main UI thread to continue.
|
||||
|
||||
### Example:
|
||||
|
||||
define(["untar"], function(untar) {
|
||||
// Load the source ArrayBuffer from a XMLHttpRequest (or any other way you may need).
|
||||
var sourceBuffer = [...];
|
||||
|
||||
untar(sourceBuffer)
|
||||
.progress(function(extractedFile) {
|
||||
...
|
||||
})
|
||||
.then(function(extractedFiles) {
|
||||
...
|
||||
});
|
||||
// or
|
||||
untar(sourceBuffer).then(
|
||||
function(extractedFiles) { // onSuccess
|
||||
...
|
||||
},
|
||||
function(err) { // onError
|
||||
...
|
||||
},
|
||||
function(extractedFile) { // onProgress
|
||||
...
|
||||
}
|
||||
);
|
||||
// Load the source ArrayBuffer from a XMLHttpRequest (or any other way you may need).
|
||||
var sourceBuffer = [...];
|
||||
|
||||
untar(sourceBuffer)
|
||||
.progress(function(extractedFile) {
|
||||
... // Do something with a single extracted file.
|
||||
})
|
||||
.then(function(extractedFiles) {
|
||||
... // Do something with all extracted files.
|
||||
});
|
||||
// or
|
||||
untar(sourceBuffer).then(
|
||||
function(extractedFiles) { // onSuccess
|
||||
... // Do something with all extracted files.
|
||||
},
|
||||
function(err) { // onError
|
||||
... // Handle the error.
|
||||
},
|
||||
function(extractedFile) { // onProgress
|
||||
... // Do something with a single extracted file.
|
||||
}
|
||||
);
|
||||
|
||||
### File object
|
||||
The returned file object(s) has the following properties. Most of these are explained in the [Tar wikipedia entry](https://en.wikipedia.org/wiki/Tar_(computing)#File_format).
|
||||
|
@ -57,7 +59,8 @@ The returned file object(s) has the following properties. Most of these are expl
|
|||
* type
|
||||
* linkname
|
||||
* ustarFormat
|
||||
* blob A [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object with the contens of the file.
|
||||
* buffer An ArrayBuffer with the contents of the file.
|
||||
* blob A [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object with the contents of the file.
|
||||
* getObjectUrl()
|
||||
A unique [ObjectUrl](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL) to the data can be retrieved with this method for easy usage of extracted data in <img> tags etc.
|
||||
document.getElementById("targetImageElement").src = file.getObjectUrl();
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
;(function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.ProgressivePromise = factory();
|
||||
}
|
||||
}(this, function() {
|
||||
"use strict";
|
||||
/* globals window: false, Promise: false */
|
||||
|
||||
/**
|
||||
Returns a Promise decorated with a progress() event.
|
||||
*/
|
||||
function ProgressivePromise(fn) {
|
||||
if (typeof Promise !== "function") {
|
||||
throw new Error("Promise implementation not available in this environment.");
|
||||
}
|
||||
|
||||
var progressCallbacks = [];
|
||||
var progressHistory = [];
|
||||
|
||||
function doProgress(value) {
|
||||
for (var i = 0, l = progressCallbacks.length; i < l; ++i) {
|
||||
progressCallbacks[i](value);
|
||||
}
|
||||
|
||||
progressHistory.push(value);
|
||||
}
|
||||
|
||||
var promise = new Promise(function(resolve, reject) {
|
||||
fn(resolve, reject, doProgress);
|
||||
});
|
||||
|
||||
promise.progress = function(cb) {
|
||||
if (typeof cb !== "function") {
|
||||
throw new Error("cb is not a function.");
|
||||
}
|
||||
|
||||
// Report the previous progress history
|
||||
for (var i = 0, l = progressHistory.length; i < l; ++i) {
|
||||
cb(progressHistory[i]);
|
||||
}
|
||||
|
||||
progressCallbacks.push(cb);
|
||||
return promise;
|
||||
};
|
||||
|
||||
var origThen = promise.then;
|
||||
|
||||
promise.then = function(onSuccess, onFail, onProgress) {
|
||||
origThen.call(promise, onSuccess, onFail);
|
||||
|
||||
if (onProgress !== undefined) {
|
||||
promise.progress(onProgress);
|
||||
}
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
return promise;
|
||||
}
|
||||
return ProgressivePromise;
|
||||
}));
|
|
@ -0,0 +1,189 @@
|
|||
"use strict";
|
||||
/* globals postMessage: false, DataView: false, self: false, window: false, ArrayBuffer: false, Uint8Array: false */
|
||||
|
||||
function UntarWorker() {
|
||||
|
||||
}
|
||||
|
||||
UntarWorker.prototype = {
|
||||
onmessage: function(msg) {
|
||||
try {
|
||||
if (msg.data.type === "extract") {
|
||||
this.untarBuffer(msg.data.buffer);
|
||||
} else {
|
||||
throw new Error("Unknown message type: " + msg.data.type);
|
||||
}
|
||||
} catch (err) {
|
||||
this.postError(err);
|
||||
}
|
||||
},
|
||||
|
||||
postError: function(err) {
|
||||
//console.info("postError(" + err.message + ")" + " " + JSON.stringify(err));
|
||||
this.postMessage({ type: "error", data: { message: err.message } });
|
||||
},
|
||||
|
||||
postLog: function(level, msg) {
|
||||
console.info("postLog");
|
||||
this.postMessage({ type: "log", data: { level: level, msg: msg }});
|
||||
},
|
||||
|
||||
untarBuffer: function(arrayBuffer) {
|
||||
try {
|
||||
var tarFileStream = new UntarFileStream(arrayBuffer);
|
||||
while (tarFileStream.hasNext()) {
|
||||
var file = tarFileStream.next();
|
||||
|
||||
this.postMessage({ type: "extract", data: file }, [file.buffer]);
|
||||
}
|
||||
|
||||
this.postMessage({ type: "complete" });
|
||||
} catch (err) {
|
||||
this.postError(err);
|
||||
}
|
||||
},
|
||||
|
||||
postMessage: function(msg, transfers) {
|
||||
console.info("postMessage(" + msg + ", " + JSON.stringify(transfers) + ")");
|
||||
self.postMessage(msg, transfers);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof self !== "undefined") {
|
||||
// We're running in a worker thread
|
||||
var worker = new UntarWorker();
|
||||
self.onmessage = function(msg) { worker.onmessage(msg); };
|
||||
}
|
||||
|
||||
function TarFile() {
|
||||
|
||||
}
|
||||
|
||||
function UntarStream(arrayBuffer) {
|
||||
this._bufferView = new DataView(arrayBuffer);
|
||||
this._position = 0;
|
||||
}
|
||||
|
||||
UntarStream.prototype = {
|
||||
readString: function(charCount) {
|
||||
//console.log("readString: position " + this.position() + ", " + charCount + " chars");
|
||||
var charSize = 1;
|
||||
var byteCount = charCount * charSize;
|
||||
|
||||
var charCodes = [];
|
||||
|
||||
for (var i = 0; i < charCount; ++i) {
|
||||
var charCode = this._bufferView.getUint8(this.position() + (i * charSize), true);
|
||||
if (charCode !== 0) {
|
||||
charCodes.push(charCode);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.seek(byteCount);
|
||||
|
||||
return String.fromCharCode.apply(null, charCodes);
|
||||
},
|
||||
|
||||
readBuffer: function(byteCount) {
|
||||
var buf;
|
||||
|
||||
if (typeof ArrayBuffer.prototype.slice === "function") {
|
||||
buf = this._bufferView.buffer.slice(this.position(), this.position() + byteCount);
|
||||
} else {
|
||||
buf = new ArrayBuffer(byteCount);
|
||||
var target = new Uint8Array(buf);
|
||||
var src = new Uint8Array(this._bufferView.buffer, this.position(), byteCount);
|
||||
target.set(src);
|
||||
}
|
||||
|
||||
this.seek(byteCount);
|
||||
return buf;
|
||||
},
|
||||
|
||||
seek: function(byteCount) {
|
||||
this._position += byteCount;
|
||||
},
|
||||
|
||||
peekUint32: function() {
|
||||
return this._bufferView.getUint32(this.position(), true);
|
||||
},
|
||||
|
||||
position: function(newpos) {
|
||||
if (newpos === undefined) {
|
||||
return this._position;
|
||||
} else {
|
||||
this._position = newpos;
|
||||
}
|
||||
},
|
||||
|
||||
size: function() {
|
||||
return this._bufferView.byteLength;
|
||||
}
|
||||
};
|
||||
|
||||
function UntarFileStream(arrayBuffer) {
|
||||
this._stream = new UntarStream(arrayBuffer);
|
||||
}
|
||||
|
||||
UntarFileStream.prototype = {
|
||||
hasNext: function() {
|
||||
// A tar file ends with 4 zero bytes
|
||||
return this._stream.position() + 4 < this._stream.size() && this._stream.peekUint32() !== 0;
|
||||
},
|
||||
|
||||
next: function() {
|
||||
var stream = this._stream;
|
||||
var file = new TarFile();
|
||||
|
||||
var headerBeginPos = stream.position();
|
||||
var dataBeginPos = headerBeginPos + 512;
|
||||
|
||||
// Read header
|
||||
file.name = stream.readString(100);
|
||||
file.mode = stream.readString(8);
|
||||
file.uid = stream.readString(8);
|
||||
file.gid = stream.readString(8);
|
||||
file.size = parseInt(stream.readString(12), 8);
|
||||
file.modificationTime = parseInt(stream.readString(12), 8);
|
||||
file.checksum = stream.readString(8);
|
||||
file.type = stream.readString(1);
|
||||
file.linkname = stream.readString(1);
|
||||
file.ustarFormat = stream.readString(6);
|
||||
|
||||
if (file.ustarFormat === "ustar") {
|
||||
file.version = stream.readString(2);
|
||||
file.uname = stream.readString(32);
|
||||
file.gname = stream.readString(32);
|
||||
file.devmajor = stream.readString(8);
|
||||
file.devminor = stream.readString(8);
|
||||
file.namePrefix = stream.readString(155);
|
||||
|
||||
if (file.namePrefix.length > 0) {
|
||||
file.name = file.namePrefix + file.name;
|
||||
}
|
||||
}
|
||||
|
||||
stream.position(dataBeginPos);
|
||||
|
||||
// Normal file is either "\0" or 0.
|
||||
if (file.type === "0" || file.type === "\0") {
|
||||
file.buffer = stream.readBuffer(file.size);
|
||||
} else if (file.type == 5) {
|
||||
// Directory - should we do anything with this? Nope!
|
||||
} else {
|
||||
// We only care about real files, not symlinks.
|
||||
}
|
||||
|
||||
if (file.buffer === undefined) {
|
||||
file.buffer = new ArrayBuffer(0);
|
||||
}
|
||||
|
||||
// File data is padded to reach a 512 byte boundary; skip the padded bytes.
|
||||
var dataEndPos = dataBeginPos + (file.size > 0 ? file.size + (512 - file.size % 512) : 0);
|
||||
stream.position(dataEndPos);
|
||||
|
||||
return file;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,91 @@
|
|||
;(function(root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(['ProgressivePromise'], factory);
|
||||
} else if (typeof exports === 'object') {
|
||||
module.exports = factory(require('ProgressivePromise'));
|
||||
} else {
|
||||
root.untar = factory(root.ProgressivePromise);
|
||||
}
|
||||
}(this, function(ProgressivePromise) {
|
||||
"use strict";
|
||||
/* globals window: false, Blob: false, Promise: false, console: false, Worker: false, ProgressivePromise: false */
|
||||
|
||||
var workerScriptUri; // Included at compile time
|
||||
|
||||
var URL = window.URL || window.webkitURL;
|
||||
|
||||
/**
|
||||
Returns a ProgressivePromise.
|
||||
*/
|
||||
function untar(arrayBuffer) {
|
||||
if (!(arrayBuffer instanceof ArrayBuffer)) {
|
||||
throw new TypeError("arrayBuffer is not an instance of ArrayBuffer.");
|
||||
}
|
||||
|
||||
if (!window.Worker) {
|
||||
throw new Error("Worker implementation not available in this environment.");
|
||||
}
|
||||
|
||||
return new ProgressivePromise(function(resolve, reject, progress) {
|
||||
var worker = new Worker(workerScriptUri);
|
||||
|
||||
var files = [];
|
||||
|
||||
worker.onerror = function(err) {
|
||||
reject(err);
|
||||
};
|
||||
|
||||
worker.onmessage = function(message) {
|
||||
message = message.data;
|
||||
|
||||
switch (message.type) {
|
||||
case "log":
|
||||
console[message.data.level]("Worker: " + message.data.msg);
|
||||
break;
|
||||
case "extract":
|
||||
var file = decorateExtractedFile(message.data);
|
||||
files.push(file);
|
||||
progress(file);
|
||||
break;
|
||||
case "complete":
|
||||
resolve(files);
|
||||
break;
|
||||
case "error":
|
||||
//console.log("error message");
|
||||
reject(new Error(message.data.message));
|
||||
break;
|
||||
default:
|
||||
reject(new Error("Unknown message from worker: " + message.type));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
//console.info("Sending arraybuffer to worker for extraction.");
|
||||
worker.postMessage({ type: "extract", buffer: arrayBuffer }, [arrayBuffer]);
|
||||
});
|
||||
}
|
||||
|
||||
function decorateExtractedFile(file) {
|
||||
var blob;
|
||||
var blobUrl;
|
||||
Object.defineProperties(file, {
|
||||
blob: {
|
||||
get: function() {
|
||||
return blob || (blob = new Blob([this.buffer]));
|
||||
}
|
||||
},
|
||||
getObjectUrl: {
|
||||
value: function() {
|
||||
return blobUrl || (blubUrl = URL.createObjectURL(blob));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
workerScriptUri = '/base/build/dev/untar-worker.js';
|
||||
return untar;
|
||||
}));
|
||||
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIiwic291cmNlcyI6WyJ1bnRhci5qcyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiBnbG9iYWxzIHdpbmRvdzogZmFsc2UsIEJsb2I6IGZhbHNlLCBQcm9taXNlOiBmYWxzZSwgY29uc29sZTogZmFsc2UsIFdvcmtlcjogZmFsc2UsIFByb2dyZXNzaXZlUHJvbWlzZTogZmFsc2UgKi9cblxudmFyIHdvcmtlclNjcmlwdFVyaTsgLy8gSW5jbHVkZWQgYXQgY29tcGlsZSB0aW1lXG5cbnZhciBVUkwgPSB3aW5kb3cuVVJMIHx8IHdpbmRvdy53ZWJraXRVUkw7XG5cbi8qKlxuUmV0dXJucyBhIFByb2dyZXNzaXZlUHJvbWlzZS5cbiovXG5mdW5jdGlvbiB1bnRhcihhcnJheUJ1ZmZlcikge1xuXHRpZiAoIShhcnJheUJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSkge1xuXHRcdHRocm93IG5ldyBUeXBlRXJyb3IoXCJhcnJheUJ1ZmZlciBpcyBub3QgYW4gaW5zdGFuY2Ugb2YgQXJyYXlCdWZmZXIuXCIpO1xuXHR9XG5cblx0aWYgKCF3aW5kb3cuV29ya2VyKSB7XG5cdFx0dGhyb3cgbmV3IEVycm9yKFwiV29ya2VyIGltcGxlbWVudGF0aW9uIG5vdCBhdmFpbGFibGUgaW4gdGhpcyBlbnZpcm9ubWVudC5cIik7XG5cdH1cblxuXHRyZXR1cm4gbmV3IFByb2dyZXNzaXZlUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3QsIHByb2dyZXNzKSB7XG5cdFx0dmFyIHdvcmtlciA9IG5ldyBXb3JrZXIod29ya2VyU2NyaXB0VXJpKTtcblxuXHRcdHZhciBmaWxlcyA9IFtdO1xuXG5cdFx0d29ya2VyLm9uZXJyb3IgPSBmdW5jdGlvbihlcnIpIHtcblx0XHRcdHJlamVjdChlcnIpO1xuXHRcdH07XG5cblx0XHR3b3JrZXIub25tZXNzYWdlID0gZnVuY3Rpb24obWVzc2FnZSkge1xuXHRcdFx0bWVzc2FnZSA9IG1lc3NhZ2UuZGF0YTtcblxuXHRcdFx0c3dpdGNoIChtZXNzYWdlLnR5cGUpIHtcblx0XHRcdFx0Y2FzZSBcImxvZ1wiOlxuXHRcdFx0XHRcdGNvbnNvbGVbbWVzc2FnZS5kYXRhLmxldmVsXShcIldvcmtlcjogXCIgKyBtZXNzYWdlLmRhdGEubXNnKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcImV4dHJhY3RcIjpcblx0XHRcdFx0XHR2YXIgZmlsZSA9IGRlY29yYXRlRXh0cmFjdGVkRmlsZShtZXNzYWdlLmRhdGEpO1xuXHRcdFx0XHRcdGZpbGVzLnB1c2goZmlsZSk7XG5cdFx0XHRcdFx0cHJvZ3Jlc3MoZmlsZSk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJjb21wbGV0ZVwiOlxuXHRcdFx0XHRcdHJlc29sdmUoZmlsZXMpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwiZXJyb3JcIjpcblx0XHRcdFx0XHQvL2NvbnNvbGUubG9nKFwiZXJyb3IgbWVzc2FnZVwiKTtcblx0XHRcdFx0XHRyZWplY3QobmV3IEVycm9yKG1lc3NhZ2UuZGF0YS5tZXNzYWdlKSk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdFx0cmVqZWN0KG5ldyBFcnJvcihcIlVua25vd24gbWVzc2FnZSBmcm9tIHdvcmtlcjogXCIgKyBtZXNzYWdlLnR5cGUpKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Ly9jb25zb2xlLmluZm8oXCJTZW5kaW5nIGFycmF5YnVmZmVyIHRvIHdvcmtlciBmb3IgZXh0cmFjdGlvbi5cIik7XG5cdFx0d29ya2VyLnBvc3RNZXNzYWdlKHsgdHlwZTogXCJleHRyYWN0XCIsIGJ1ZmZlcjogYXJyYXlCdWZmZXIgfSwgW2FycmF5QnVmZmVyXSk7XG5cdH0pO1xufVxuXG5mdW5jdGlvbiBkZWNvcmF0ZUV4dHJhY3RlZEZpbGUoZmlsZSkge1xuXHR2YXIgYmxvYjtcblx0dmFyIGJsb2JVcmw7XG5cdE9iamVjdC5kZWZpbmVQcm9wZXJ0aWVzKGZpbGUsIHtcblx0XHRibG9iOiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRyZXR1cm4gYmxvYiB8fCAoYmxvYiA9IG5ldyBCbG9iKFt0aGlzLmJ1ZmZlcl0pKTtcblx0XHRcdH1cblx0XHR9LFxuXHRcdGdldE9iamVjdFVybDoge1xuXHRcdFx0dmFsdWU6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRyZXR1cm4gYmxvYlVybCB8fCAoYmx1YlVybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwoYmxvYikpO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG5cblx0cmV0dXJuIGZpbGU7XG59XG4iXSwiZmlsZSI6InVudGFyLmpzIiwic291cmNlUm9vdCI6Ii9zb3VyY2UvIn0=
|
|
@ -0,0 +1 @@
|
|||
!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.untar=t()}(this,function(){"use strict";function e(e){function t(e){for(var t=0,i=r.length;i>t;++t)r[t](e);n.push(e)}if("function"!=typeof Promise)throw new Error("Promise implementation not available in this environment.");var r=[],n=[],i=new Promise(function(r,n){e(r,n,t)});i.progress=function(e){if("function"!=typeof e)throw new Error("cb is not a function.");for(var t=0,o=n.length;o>t;++t)e(n[t]);return r.push(e),i};var o=i.then;return i.then=function(e,t,r){return o.call(i,e,t),void 0!==r&&i.progress(r),i},i}function t(t){if(!(t instanceof ArrayBuffer))throw new TypeError("arrayBuffer is not an instance of ArrayBuffer.");if(!window.Worker)throw new Error("Worker implementation not available in this environment.");return new e(function(e,i,o){var a=new Worker(n),s=[];a.onerror=function(e){i(e)},a.onmessage=function(t){switch(t=t.data,t.type){case"log":console[t.data.level]("Worker: "+t.data.msg);break;case"extract":var n=r(t.data);s.push(n),o(n);break;case"complete":e(s);break;case"error":i(new Error(t.data.message));break;default:i(new Error("Unknown message from worker: "+t.type))}},a.postMessage({type:"extract",buffer:t},[t])})}function r(e){var t,r;return Object.defineProperties(e,{blob:{get:function(){return t||(t=new Blob([this.buffer]))}},getObjectUrl:{value:function(){return r||(blubUrl=i.createObjectURL(t))}}}),e}var n,i=window.URL||window.webkitURL;return n=i.createObjectURL(new Blob(['"use strict";function UntarWorker(){}function TarFile(){}function UntarStream(e){this._bufferView=new DataView(e),this._position=0}function UntarFileStream(e){this._stream=new UntarStream(e)}if(UntarWorker.prototype={onmessage:function(e){try{if("extract"!==e.data.type)throw new Error("Unknown message type: "+e.data.type);this.untarBuffer(e.data.buffer)}catch(t){this.postError(t)}},postError:function(e){this.postMessage({type:"error",data:{message:e.message}})},postLog:function(e,t){console.info("postLog"),this.postMessage({type:"log",data:{level:e,msg:t}})},untarBuffer:function(e){try{for(var t=new UntarFileStream(e);t.hasNext();){var r=t.next();this.postMessage({type:"extract",data:r},[r.buffer])}this.postMessage({type:"complete"})}catch(i){this.postError(i)}},postMessage:function(e,t){console.info("postMessage("+e+", "+JSON.stringify(t)+")"),self.postMessage(e,t)}},"undefined"!=typeof self){var worker=new UntarWorker;self.onmessage=function(e){worker.onmessage(e)}}UntarStream.prototype={readString:function(e){for(var t=1,r=e*t,i=[],n=0;e>n;++n){var s=this._bufferView.getUint8(this.position()+n*t,!0);if(0===s)break;i.push(s)}return this.seek(r),String.fromCharCode.apply(null,i)},readBuffer:function(e){var t;if("function"==typeof ArrayBuffer.prototype.slice)t=this._bufferView.buffer.slice(this.position(),this.position()+e);else{t=new ArrayBuffer(e);var r=new Uint8Array(t),i=new Uint8Array(this._bufferView.buffer,this.position(),e);r.set(i)}return this.seek(e),t},seek:function(e){this._position+=e},peekUint32:function(){return this._bufferView.getUint32(this.position(),!0)},position:function(e){return void 0===e?this._position:void(this._position=e)},size:function(){return this._bufferView.byteLength}},UntarFileStream.prototype={hasNext:function(){return this._stream.position()+4<this._stream.size()&&0!==this._stream.peekUint32()},next:function(){var e=this._stream,t=new TarFile,r=e.position(),i=r+512;t.name=e.readString(100),t.mode=e.readString(8),t.uid=e.readString(8),t.gid=e.readString(8),t.size=parseInt(e.readString(12),8),t.modificationTime=parseInt(e.readString(12),8),t.checksum=e.readString(8),t.type=e.readString(1),t.linkname=e.readString(1),t.ustarFormat=e.readString(6),"ustar"===t.ustarFormat&&(t.version=e.readString(2),t.uname=e.readString(32),t.gname=e.readString(32),t.devmajor=e.readString(8),t.devminor=e.readString(8),t.namePrefix=e.readString(155),t.namePrefix.length>0&&(t.name=t.namePrefix+t.name)),e.position(i),"0"===t.type||"\x00"===t.type?t.buffer=e.readBuffer(t.size):5==t.type,void 0===t.buffer&&(t.buffer=new ArrayBuffer(0));var n=i+(t.size>0?t.size+(512-t.size%512):0);return e.position(n),t}};'])),t});
|
|
@ -26,7 +26,6 @@
|
|||
},
|
||||
"homepage": "https://github.com/Qvazar/js-untar",
|
||||
"devDependencies": {
|
||||
"es6-promise": "^3.0.2",
|
||||
"gulp": "^3.9.0",
|
||||
"gulp-add-src": "^0.2.0",
|
||||
"gulp-concat": "^2.6.0",
|
||||
|
@ -42,9 +41,7 @@
|
|||
"karma-firefox-launcher": "^0.1.6",
|
||||
"karma-ie-launcher": "^0.2.0",
|
||||
"karma-jasmine": "^0.3.6",
|
||||
"karma-phantomjs-launcher": "^0.2.1",
|
||||
"karma-requirejs": "^0.2.2",
|
||||
"phantomjs": "^1.9.18",
|
||||
"requirejs": "^2.1.20"
|
||||
}
|
||||
}
|
||||
|
|
23
src/untar.js
23
src/untar.js
|
@ -56,17 +56,20 @@ function untar(arrayBuffer) {
|
|||
}
|
||||
|
||||
function decorateExtractedFile(file) {
|
||||
file.blob = new Blob([file.buffer]);
|
||||
delete file.buffer;
|
||||
|
||||
var blob;
|
||||
var blobUrl;
|
||||
file.getObjectUrl = function() {
|
||||
if (!blobUrl) {
|
||||
blobUrl = URL.createObjectURL(file.blob);
|
||||
Object.defineProperties(file, {
|
||||
blob: {
|
||||
get: function() {
|
||||
return blob || (blob = new Blob([this.buffer]));
|
||||
}
|
||||
},
|
||||
getObjectUrl: {
|
||||
value: function() {
|
||||
return blobUrl || (blubUrl = URL.createObjectURL(blob));
|
||||
}
|
||||
}
|
||||
|
||||
return blobUrl;
|
||||
};
|
||||
});
|
||||
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue