Created
May 19, 2012 13:48
-
-
Save auroranockert/2730903 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset='utf-8'> | |
<title>file.js</title> | |
<script> | |
function file(url, callback) { | |
this.url = url, this.pagesize = 65536 | |
var request = new XMLHttpRequest() | |
request.open("HEAD", this.url, true) | |
var self = this | |
request.addEventListener("load", function () { | |
self.length = parseInt(request.getResponseHeader("Content-length"), 10) | |
self.pages = Math.ceil(self.length / self.pagesize), self.open = true | |
self.status = new Array(self.pages), self.data = new ArrayBuffer(self.length) | |
callback(self) | |
}, false) | |
request.addEventListener("error", function () { | |
self.open = false | |
callback(self) | |
}, false) | |
request.send() | |
} | |
file.prototype.prefetch = function (offset, length) { | |
this.read(offset, length) | |
} | |
file.prototype.readPages = function (start, pages, positive, negative) { | |
if (pages < 1) { | |
positive(); return | |
} | |
var request = new XMLHttpRequest() | |
request.open("GET", this.url, true) | |
request.responseType = "arraybuffer" | |
request.setRequestHeader("Range", "bytes=" + (start * this.pagesize) + "-" + ((start + pages) * this.pagesize - 1)) | |
var self = this | |
request.addEventListener("load", function () { | |
var sourceView = new Uint8Array(request.response) | |
var destinationView = new Uint8Array(self.data, start * self.pagesize, pages * self.pagesize) | |
destinationView.set(sourceView) | |
for (var i = 0; i < pages; i++) { | |
self.status[start + i] = true | |
} | |
positive() | |
}, true) | |
for (var i = 0; i < pages; i++) { | |
this.status[start + i] = request | |
} | |
request.addEventListener("error", negative, false) | |
request.send() | |
} | |
file.prototype.read = function (offset, length, callback) { | |
var self = this | |
var startpage = Math.floor(offset / this.pagesize), pages = Math.ceil(length / this.pagesize) | |
var connections = 1, finished = 0, failed = 0 | |
function transferComplete() { | |
finished += 1 | |
if (callback && (finished == connections)) { | |
if (failed == 0) { | |
callback(self, new DataView(self.data, offset, length)) | |
} else { | |
callback(self) | |
} | |
} | |
} | |
function transferFailed () { | |
finished += 1; failed += 1 | |
if (callback && (finished == connections)) { | |
callback(self) | |
} | |
} | |
var start = pages, inRange = false | |
for (var i = 0; i < pages; i++) { | |
var value = this.status[startpage + i] | |
if (value) { | |
if (inRange) { | |
connections += 1 | |
this.readPages(startpage + start, i - start, transferComplete, transferFailed) | |
inRange = false | |
} | |
if (value !== true) { | |
connections += 1 | |
value.addEventListener("load", function () { transferComplete() }, false) /* Stupid addEventListener… */ | |
value.addEventListener("error", function () { transferFailed() }, false) | |
} | |
} else { | |
if (!inRange) { | |
inRange = true, start = i | |
} | |
} | |
} | |
this.readPages(startpage + start, pages - start, transferComplete, transferFailed) | |
} | |
f = new file("[email protected]", function (file) { | |
file.prefetch(8 * file.pagesize, file.pagesize) | |
file.prefetch(0, 16 * file.pagesize) | |
file.read(0, 16 * file.pagesize, function (file, data) { | |
console.log("Here!") | |
}) | |
}) | |
</script> | |
</head> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment