-
Notifications
You must be signed in to change notification settings - Fork 0
/
file-registry.coffee
114 lines (102 loc) · 4.13 KB
/
file-registry.coffee
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
FileRegistry = new Mongo.Collection 'fileRegistry'
###@FileRegistry.attachSchema new SimpleSchema
filename:
type: String
filenameOnDisk:
type: String
size:
type: Number
timestamp:
type: new Date()
userId:
type: String
###
if Meteor.isClient
FileRegistry.serveFile = ->
return
if Meteor.isServer
endsWithAnyOf = (filename, extensions) ->
check filename, String
check extensions, Array
f = filename.toLowerCase()
for e in extensions
if f.lastIndexOf(e.toLowerCase()) is f.length-e.length then return true
return false
FileRegistry.getFileRoot = ->
fs = Npm.require 'fs'
filePath = process.cwd()
localPathIndex = filePath.indexOf('.meteor/local')
filePath = filePath.substr(0, localPathIndex)+'.meteor' if localPathIndex > -1
return filePath + '/files/'
FileRegistry.scheduleJobsForFile = (filenameOnDisk) ->
images = ['jpg', 'jpeg', 'png', 'gif', 'tif', 'tiff', 'tga', 'bmp', 'cr2']
videos = ['mp4', 'mpeg', 'avi', 'mov', 'webm', 'flv', 'mkv', '3gp', 'm4v', '3g2', 'm2v', 'wmv']
other = ['pdf', 'txt']
Job.push new Md5Job filenameOnDisk: filenameOnDisk
if endsWithAnyOf filenameOnDisk, images.concat(videos).concat(other)
Job.push new ThumbnailJob filenameOnDisk: filenameOnDisk
if endsWithAnyOf filenameOnDisk, videos
targetType = Meteor.settings.fileRegistry?.videoTargetType? or 'mp4'
unless filenameOnDisk.toLowerCase().lastIndexOf(targetType.toLowerCase()) is filenameOnDisk.length-targetType.length #Don't convert something to the same type.
Job.push new VideoTranscodeJob filenameOnDisk: filenameOnDisk, targetType: targetType
# Generates an action handler to serve files via iron:router server routes
# example:
# @route 'serveFile',
# path: '/file/:filename'
# where: 'server'
# action: FileRegistry.serveFile
FileRegistry.serveFile = (options) ->
options = _.extend
disposition: 'inline'
allowAccess: -> true
, options
serveFile = ->
check @params.filename, String
fs = Npm.require 'fs'
# TODO verify file exists
grantAccess = options.allowAccess.call @
unless grantAccess
@response.status(403).end()
return
expire = new Date()
expire.setFullYear(expire.getFullYear()+1)
fn = FileRegistry.getFileRoot() + @params.filename
fd = fs.openSync fn, 'r'
try
stat = fs.fstatSync fd
mimeType = Npm.require('mime').lookup fn
if @request.headers.range?
start = parseInt(@request.headers.range.substr('bytes='.length))
end = parseInt(@request.headers.range.split('-').pop())
bufferSize = if isNaN(end) then Math.min(1024*1024,stat.size) else (1+end-start)
console.log 'bufferSize: ', bufferSize
buffer = new Buffer(bufferSize)
bytesRead = fs.readSync fd, buffer, 0, bufferSize, Math.min(start, stat.size)
@response.writeHead 206,
'Content-Range': 'bytes '+start+'-'+(start+bytesRead-1) + '/' + stat.size
'Content-Length': bytesRead
'Content-Type': mimeType
'Accept-Ranges': 'bytes'
'Cache-Control': 'no-cache'
@response.end buffer.slice(0,bytesRead)
else
acceptableFilename = @params.filename
acceptableFilename = acceptableFilename.substr(acceptableFilename.indexOf('-')+1)
acceptableFilename = acceptableFilename.substr(acceptableFilename.indexOf('-')+1)
acceptableFilename = encodeURIComponent acceptableFilename
@response.writeHead 200,
'Content-type': mimeType
'Content-Disposition': "#{options.disposition}; filename*=UTF-8''#{acceptableFilename}"
'Expires': moment(expire).format('ddd, DD MMM YYYY HH:mm:ss GMT')
@response.end fs.readFileSync fn
catch e
console.log 'exception from request: ', @params.filename, @request.headers.range
console.log e
finally
fs.closeSync fd
if @params?
serveFile.call @
else
# Maintain compatibility with pre-0.9.8, where
# serveFile was passed directly to router action
serveFile