1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
module.exports = File
var appendTo = require('./append-to')
var eos = require('end-of-stream')
var EventEmitter = require('events').EventEmitter
var FileStream = require('./file-stream')
var inherits = require('inherits')
var mime = require('./mime.json')
var path = require('path')
inherits(File, EventEmitter)
/**
* @param {Torrent} torrent torrent that the file belongs to
* @param {Object} file file object from the parsed torrent
*/
function File (torrent, file) {
EventEmitter.call(this)
this._torrent = torrent
this.name = file.name
this.path = file.path
this.length = file.length
this.offset = file.offset
this.done = (this.length === 0)
var start = file.offset
var end = start + file.length - 1
this._startPiece = start / this._torrent.pieceLength | 0
this._endPiece = end / this._torrent.pieceLength | 0
}
/**
* Selects the file to be downloaded, but at a lower priority than files with streams.
* Useful if you know you need the file at a later stage.
*/
File.prototype.select = function () {
if (this.length === 0) return
this._torrent.select(this._startPiece, this._endPiece, false)
}
/**
* Deselects the file, which means it won't be downloaded unless someone creates a stream
* for it.
*/
File.prototype.deselect = function () {
if (this.length === 0) return
this._torrent.deselect(this._startPiece, this._endPiece, false)
}
/**
* Create a readable stream to the file. Pieces needed by the stream will be prioritized
* highly and fetched from the swarm first.
*
* @param {Object} opts
* @param {number} opts.start stream slice of file, starting from this byte (inclusive)
* @param {number} opts.end stream slice of file, ending with this byte (inclusive)
* @return {FileStream}
*/
File.prototype.createReadStream = function (opts) {
var self = this
var stream = new FileStream(self, opts)
self._torrent.select(stream._startPiece, stream._endPiece, true, function () {
stream._notify()
})
eos(stream, function () {
self._torrent.deselect(stream._startPiece, stream._endPiece, true)
})
return stream
}
/**
* @param {function} cb
*/
File.prototype.getBuffer = function (cb) {
var buf = new Buffer(this.length)
var offset = 0
this.createReadStream()
.on('data', function (chunk) {
chunk.copy(buf, offset)
offset += chunk.length
})
.on('end', function () {
cb(null, buf)
})
.on('error', cb)
}
/**
* @param {function} cb
*/
File.prototype.getBlobURL = function (cb) {
var self = this
if (typeof window === 'undefined') throw new Error('browser-only method')
self.getBuffer(function (err, buffer) {
if (err) return cb(err)
var ext = path.extname(self.name).toLowerCase()
var type = mime[ext]
var blob = new window.Blob([ buffer ], type && { type: type })
var url = window.URL.createObjectURL(blob)
cb(null, url)
})
}
/**
* Show the file in a the browser by appending it to the DOM.
* @param {Element|string} elem
* @param {function} cb
*/
File.prototype.appendTo = function (elem, cb) {
if (typeof window === 'undefined') throw new Error('browser-only method')
if (typeof elem === 'string') elem = document.querySelector(elem)
appendTo(this, elem, cb)
}
|