Skip to content

Instantly share code, notes, and snippets.

@auroranockert
Created May 19, 2012 13:48
Show Gist options
  • Save auroranockert/2730903 to your computer and use it in GitHub Desktop.
Save auroranockert/2730903 to your computer and use it in GitHub Desktop.
<!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