Convert File Package to js

pull/6503/head
Martin Schoeler 9 years ago
parent 9508f2cb44
commit c8efc71bb2
  1. 256
      packages/rocketchat-file/file.server.coffee
  2. 308
      packages/rocketchat-file/file.server.js
  3. 3
      packages/rocketchat-file/package.js

@ -1,256 +0,0 @@
Grid = Npm.require('gridfs-stream')
stream = Npm.require('stream')
fs = Npm.require('fs')
path = Npm.require('path')
mkdirp = Npm.require('mkdirp')
gm = Npm.require('gm')
exec = Npm.require('child_process').exec
# Fix problem with usernames being converted to object id
Grid.prototype.tryParseObjectId = -> false
RocketChatFile =
gm: gm
enabled: undefined
enable: ->
RocketChatFile.enabled = true
RocketChat.settings.updateOptionsById 'Accounts_AvatarResize', {alert: undefined}
disable: ->
RocketChatFile.enabled = false
RocketChat.settings.updateOptionsById 'Accounts_AvatarResize', {alert: 'The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server'}
detectGM = ->
exec 'gm version', Meteor.bindEnvironment (error, stdout, stderr) ->
if not error? and stdout.indexOf('GraphicsMagick') > -1
RocketChatFile.enable()
RocketChat.Info.GraphicsMagick =
enabled: true
version: stdout
else
RocketChat.Info.GraphicsMagick =
enabled: false
exec 'convert -version', Meteor.bindEnvironment (error, stdout, stderr) ->
if not error? and stdout.indexOf('ImageMagick') > -1
if RocketChatFile.enabled isnt true
# Enable GM to work with ImageMagick if no GraphicsMagick
RocketChatFile.gm = RocketChatFile.gm.subClass({imageMagick: true})
RocketChatFile.enable()
RocketChat.Info.ImageMagick =
enabled: true
version: stdout
else
if RocketChatFile.enabled isnt true
RocketChatFile.disable()
RocketChat.Info.ImageMagick =
enabled: false
detectGM()
Meteor.methods
'detectGM': ->
detectGM()
return
RocketChatFile.bufferToStream = (buffer) ->
bufferStream = new stream.PassThrough()
bufferStream.end buffer
return bufferStream
RocketChatFile.dataURIParse = (dataURI) ->
imageData = dataURI.split ';base64,'
return {
image: imageData[1]
contentType: imageData[0].replace('data:', '')
}
RocketChatFile.addPassThrough = (st, fn) ->
pass = new stream.PassThrough()
fn pass, st
return pass
RocketChatFile.GridFS = class
constructor: (config={}) ->
{name, transformWrite} = config
name ?= 'file'
this.name = name
this.transformWrite = transformWrite
mongo = Package.mongo.MongoInternals.NpmModule
db = Package.mongo.MongoInternals.defaultRemoteCollectionDriver().mongo.db
this.store = new Grid(db, mongo)
this.findOneSync = Meteor.wrapAsync this.store.collection(this.name).findOne.bind this.store.collection(this.name)
this.removeSync = Meteor.wrapAsync this.store.remove.bind this.store
this.getFileSync = Meteor.wrapAsync this.getFile.bind this
findOne: (fileName) ->
return this.findOneSync {_id: fileName}
remove: (fileName) ->
return this.removeSync
_id: fileName
root: this.name
createWriteStream: (fileName, contentType) ->
self = this
ws = this.store.createWriteStream
_id: fileName
filename: fileName
mode: 'w'
root: this.name
content_type: contentType
if self.transformWrite?
ws = RocketChatFile.addPassThrough ws, (rs, ws) ->
file =
name: self.name
fileName: fileName
contentType: contentType
self.transformWrite file, rs, ws
ws.on 'close', ->
ws.emit 'end'
return ws
createReadStream: (fileName) ->
return this.store.createReadStream
_id: fileName
root: this.name
return undefined
getFileWithReadStream: (fileName) ->
file = this.findOne fileName
if not file?
return undefined
rs = this.createReadStream fileName
return {
readStream: rs
contentType: file.contentType
length: file.length
uploadDate: file.uploadDate
}
getFile: (fileName, cb) ->
file = this.getFileWithReadStream(fileName)
if not file
return cb()
data = []
file.readStream.on 'data', Meteor.bindEnvironment (chunk) ->
data.push chunk
file.readStream.on 'end', Meteor.bindEnvironment ->
cb null,
buffer: Buffer.concat(data)
contentType: file.contentType
length: file.length
uploadDate: file.uploadDate
deleteFile: (fileName) ->
file = this.findOne fileName
if not file?
return undefined
return this.remove fileName
RocketChatFile.FileSystem = class
constructor: (config={}) ->
{absolutePath, transformWrite} = config
absolutePath ?= '~/uploads'
this.transformWrite = transformWrite
if absolutePath.split(path.sep)[0] is '~'
homepath = process.env.HOME or process.env.HOMEPATH or process.env.USERPROFILE
if homepath?
absolutePath = absolutePath.replace '~', homepath
else
throw new Error('Unable to resolve "~" in path')
this.absolutePath = path.resolve absolutePath
mkdirp.sync this.absolutePath
this.statSync = Meteor.wrapAsync fs.stat.bind fs
this.unlinkSync = Meteor.wrapAsync fs.unlink.bind fs
this.getFileSync = Meteor.wrapAsync this.getFile.bind this
createWriteStream: (fileName, contentType) ->
self = this
ws = fs.createWriteStream path.join this.absolutePath, fileName
if self.transformWrite?
ws = RocketChatFile.addPassThrough ws, (rs, ws) ->
file =
fileName: fileName
contentType: contentType
self.transformWrite file, rs, ws
ws.on 'close', ->
ws.emit 'end'
return ws
createReadStream: (fileName) ->
return fs.createReadStream path.join this.absolutePath, fileName
stat: (fileName) ->
return this.statSync path.join this.absolutePath, fileName
remove: (fileName) ->
return this.unlinkSync path.join this.absolutePath, fileName
getFileWithReadStream: (fileName) ->
try
stat = this.stat fileName
rs = this.createReadStream fileName
return {
readStream: rs
# contentType: file.contentType
length: stat.size
}
catch e
return undefined
getFile: (fileName, cb) ->
file = this.getFileWithReadStream(fileName)
if not file
return cb()
data = []
file.readStream.on 'data', Meteor.bindEnvironment (chunk) ->
data.push chunk
file.readStream.on 'end', Meteor.bindEnvironment ->
buffer: Buffer.concat(data)
contentType: file.contentType
length: file.length
uploadDate: file.uploadDate
deleteFile: (fileName) ->
try
stat = this.stat fileName
return this.remove fileName
catch e
return undefined

@ -0,0 +1,308 @@
const Grid = Npm.require('gridfs-stream');
const stream = Npm.require('stream');
const fs = Npm.require('fs');
const path = Npm.require('path');
const mkdirp = Npm.require('mkdirp');
const gm = Npm.require('gm');
const exec = Npm.require('child_process').exec;
Grid.tryParseObjectId = function() {
return false;
};
//TODO: REMOVE RocketChatFile from globals
RocketChatFile = {
gm,
enabled: undefined,
enable() {
RocketChatFile.enabled = true;
return RocketChat.settings.updateOptionsById('Accounts_AvatarResize', {
alert: undefined
});
},
disable() {
RocketChatFile.enabled = false;
return RocketChat.settings.updateOptionsById('Accounts_AvatarResize', {
alert: 'The_image_resize_will_not_work_because_we_can_not_detect_ImageMagick_or_GraphicsMagick_installed_in_your_server'
});
}
};
const detectGM = function() {
return exec('gm version', Meteor.bindEnvironment(function(error, stdout) {
if ((error == null) && stdout.indexOf('GraphicsMagick') > -1) {
RocketChatFile.enable();
RocketChat.Info.GraphicsMagick = {
enabled: true,
version: stdout
};
} else {
RocketChat.Info.GraphicsMagick = {
enabled: false
};
}
return exec('convert -version', Meteor.bindEnvironment(function(error, stdout) {
if ((error == null) && stdout.indexOf('ImageMagick') > -1) {
if (RocketChatFile.enabled !== true) {
RocketChatFile.gm = RocketChatFile.gm.subClass({
imageMagick: true
});
RocketChatFile.enable();
}
return RocketChat.Info.ImageMagick = {
enabled: true,
version: stdout
};
} else {
if (RocketChatFile.enabled !== true) {
RocketChatFile.disable();
}
return RocketChat.Info.ImageMagick = {
enabled: false
};
}
}));
}));
};
detectGM();
Meteor.methods({
'detectGM'() {
detectGM();
}
});
RocketChatFile.bufferToStream = function(buffer) {
const bufferStream = new stream.PassThrough();
bufferStream.end(buffer);
return bufferStream;
};
RocketChatFile.dataURIParse = function(dataURI) {
const imageData = dataURI.split(';base64,');
return {
image: imageData[1],
contentType: imageData[0].replace('data:', '')
};
};
RocketChatFile.addPassThrough = function(st, fn) {
const pass = new stream.PassThrough();
fn(pass, st);
return pass;
};
RocketChatFile.GridFS = class {
constructor(config) {
if (config == null) {
config = {};
}
let name = config.name;
const transformWrite = config.transformWrite;
if (name == null) {
name = 'file';
}
this.name = name;
this.transformWrite = transformWrite;
const mongo = Package.mongo.MongoInternals.NpmModule;
const db = Package.mongo.MongoInternals.defaultRemoteCollectionDriver().mongo.db;
this.store = new Grid(db, mongo);
this.findOneSync = Meteor.wrapAsync(this.store.collection(this.name).findOne.bind(this.store.collection(this.name)));
this.removeSync = Meteor.wrapAsync(this.store.remove.bind(this.store));
this.getFileSync = Meteor.wrapAsync(this.getFile.bind(this));
}
findOne(fileName) {
return this.findOneSync({
_id: fileName
});
}
remove(fileName) {
return this.removeSync({
_id: fileName,
root: this.name
});
}
createWriteStream(fileName, contentType) {
const self = this;
let ws = this.store.createWriteStream({
_id: fileName,
filename: fileName,
mode: 'w',
root: this.name,
content_type: contentType
});
if (self.transformWrite != null) {
ws = RocketChatFile.addPassThrough(ws, function(rs, ws) {
const file = {
name: self.name,
fileName,
contentType
};
return self.transformWrite(file, rs, ws);
});
}
ws.on('close', function() {
return ws.emit('end');
});
return ws;
}
createReadStream(fileName) {
return this.store.createReadStream({
_id: fileName,
root: this.name
});
}
getFileWithReadStream(fileName) {
const file = this.findOne(fileName);
if (file == null) {
return null;
}
const rs = this.createReadStream(fileName);
return {
readStream: rs,
contentType: file.contentType,
length: file.length,
uploadDate: file.uploadDate
};
}
getFile(fileName, cb) {
const file = this.getFileWithReadStream(fileName);
if (!file) {
return cb();
}
const data = [];
file.readStream.on('data', Meteor.bindEnvironment(function(chunk) {
return data.push(chunk);
}));
return file.readStream.on('end', Meteor.bindEnvironment(function() {
return cb(null, {
buffer: Buffer.concat(data),
contentType: file.contentType,
length: file.length,
uploadDate: file.uploadDate
});
}));
}
deleteFile(fileName) {
const file = this.findOne(fileName);
if (file == null) {
return null;
}
return this.remove(fileName);
}
};
RocketChatFile.FileSystem = class {
constructor(config) {
if (config == null) {
config = {};
}
let absolutePath = config.absolutePath;
const transformWrite = config.transformWrite;
if (absolutePath == null) {
absolutePath = '~/uploads';
}
this.transformWrite = transformWrite;
if (absolutePath.split(path.sep)[0] === '~') {
const homepath = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE;
if (homepath != null) {
absolutePath = absolutePath.replace('~', homepath);
} else {
throw new Error('Unable to resolve "~" in path');
}
}
this.absolutePath = path.resolve(absolutePath);
mkdirp.sync(this.absolutePath);
this.statSync = Meteor.wrapAsync(fs.stat.bind(fs));
this.unlinkSync = Meteor.wrapAsync(fs.unlink.bind(fs));
this.getFileSync = Meteor.wrapAsync(this.getFile.bind(this));
}
createWriteStream(fileName, contentType) {
const self = this;
let ws = fs.createWriteStream(path.join(this.absolutePath, fileName));
if (self.transformWrite != null) {
ws = RocketChatFile.addPassThrough(ws, function(rs, ws) {
const file = {
fileName,
contentType
};
return self.transformWrite(file, rs, ws);
});
}
ws.on('close', function() {
return ws.emit('end');
});
return ws;
}
createReadStream(fileName) {
return fs.createReadStream(path.join(this.absolutePath, fileName));
}
stat(fileName) {
return this.statSync(path.join(this.absolutePath, fileName));
}
remove(fileName) {
return this.unlinkSync(path.join(this.absolutePath, fileName));
}
getFileWithReadStream(fileName) {
try {
const stat = this.stat(fileName);
const rs = this.createReadStream(fileName);
return {
readStream: rs,
length: stat.size
};
} catch (error1) {
return null;
}
}
getFile(fileName, cb) {
const file = this.getFileWithReadStream(fileName);
if (!file) {
return cb();
}
const data = [];
file.readStream.on('data', Meteor.bindEnvironment(function(chunk) {
return data.push(chunk);
}));
return file.readStream.on('end', Meteor.bindEnvironment(function() {
return {
buffer: Buffer.concat(data)({
contentType: file.contentType,
length: file.length,
uploadDate: file.uploadDate
})
};
}));
}
deleteFile(fileName) {
try {
return this.remove(fileName);
} catch (error1) {
return null;
}
}
};

@ -8,10 +8,9 @@ Package.describe({
Package.onUse(function(api) {
api.use('rocketchat:lib');
api.use('rocketchat:version');
api.use('coffeescript');
api.use('ecmascript');
api.addFiles('file.server.coffee', 'server');
api.addFiles('file.server.js', 'server');
api.export('RocketChatFile', 'server');
});

Loading…
Cancel
Save