Skip to content

Commit 1756e76

Browse files
committed
Refactoring imageRouter to modularity
This should make the imageRouter more modular and easier to extent. Also a lot of code duplication was removed which should simplify maintenance in future. In the new setup we only need to provide a new module file which exports a function called `uploadImage` and takes a filePath and a callback as argument. The callback itself takes an error and an url as parameter. This eliminates the need of a try-catch-block around the statement and re-enabled the optimization in NodeJS. Signed-off-by: Sheogorath <sheogorath@shivering-isles.com>
1 parent 9cbe03d commit 1756e76

7 files changed

Lines changed: 190 additions & 132 deletions

File tree

lib/config/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const path = require('path')
66
const {merge} = require('lodash')
77
const deepFreeze = require('deep-freeze')
88
const {Environment, Permission} = require('./enum')
9+
const logger = require('../logger')
910

1011
const appRootPath = path.join(__dirname, '../../')
1112
const env = process.env.NODE_ENV || Environment.development
@@ -103,6 +104,12 @@ if (config.imageUploadType && !config.imageuploadtype) {
103104
config.imageuploadtype = config.imageUploadType
104105
}
105106

107+
// Validate upload upload providers
108+
if (['filesystem', 's3', 'minio', 'imgur'].indexOf(config.imageuploadtype) === -1) {
109+
logger.error('"imageuploadtype" is not correctly set. Please use "filesystem", "s3", "minio" or "imgur". Defaulting to "imgur"')
110+
config.imageuploadtype = 'imgur'
111+
}
112+
106113
// figure out mime types for image uploads
107114
switch (config.imageuploadtype) {
108115
case 'imgur':

lib/web/imageRouter.js

Lines changed: 0 additions & 132 deletions
This file was deleted.

lib/web/imageRouter/filesystem.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict'
2+
const url = require('url')
3+
4+
const config = require('../../config')
5+
6+
exports.uploadImage = function (imagePath, callback) {
7+
if (!imagePath || typeof imagePath !== 'string') {
8+
callback(new Error('Image path is missing or wrong'), null)
9+
return
10+
}
11+
12+
if (!callback || typeof callback !== 'function') {
13+
callback(new Error('Callback has to be a function'), null)
14+
return
15+
}
16+
17+
callback(null, url.resolve(config.serverurl + '/', imagePath.match(/^public\/(.+$)/)[1]))
18+
}

lib/web/imageRouter/imgur.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
'use strict'
2+
const config = require('../../config')
3+
const logger = require('../../logger')
4+
5+
const imgur = require('imgur')
6+
7+
exports.uploadImage = function (imagePath, callback) {
8+
if (!imagePath || typeof imagePath !== 'string') {
9+
callback(new Error('Image path is missing or wrong'), null)
10+
return
11+
}
12+
13+
if (!callback || typeof callback !== 'function') {
14+
callback(new Error('Callback has to be a function'), null)
15+
return
16+
}
17+
18+
imgur.setClientId(config.imgur.clientID)
19+
imgur.uploadFile(imagePath)
20+
.then(function (json) {
21+
if (config.debug) {
22+
logger.info('SERVER uploadimage success: ' + JSON.stringify(json))
23+
}
24+
callback(null, json.data.link.replace(/^http:\/\//i, 'https://'))
25+
}).catch(function (err) {
26+
callback(new Error(err), null)
27+
})
28+
}

lib/web/imageRouter/index.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict'
2+
3+
const Router = require('express').Router
4+
const formidable = require('formidable')
5+
6+
const config = require('../../config')
7+
const logger = require('../../logger')
8+
const response = require('../../response')
9+
10+
const imageRouter = module.exports = Router()
11+
12+
// upload image
13+
imageRouter.post('/uploadimage', function (req, res) {
14+
var form = new formidable.IncomingForm()
15+
16+
form.keepExtensions = true
17+
18+
if (config.imageuploadtype === 'filesystem') {
19+
form.uploadDir = 'public/uploads'
20+
}
21+
22+
form.parse(req, function (err, fields, files) {
23+
if (err || !files.image || !files.image.path) {
24+
response.errorForbidden(res)
25+
} else {
26+
if (config.debug) {
27+
logger.info('SERVER received uploadimage: ' + JSON.stringify(files.image))
28+
}
29+
30+
const uploadProvider = require('./' + config.imageuploadtype)
31+
uploadProvider.uploadImage(files.image.path, function (err, url) {
32+
if (err !== null) {
33+
logger.error(err)
34+
return res.status(500).end('upload image error')
35+
}
36+
res.send({
37+
link: url
38+
})
39+
})
40+
}
41+
})
42+
})

lib/web/imageRouter/minio.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use strict'
2+
const fs = require('fs')
3+
const path = require('path')
4+
5+
const config = require('../../config')
6+
const {getImageMimeType} = require('../../utils')
7+
8+
const Minio = require('minio')
9+
const minioClient = new Minio.Client({
10+
endPoint: config.minio.endPoint,
11+
port: config.minio.port,
12+
secure: config.minio.secure,
13+
accessKey: config.minio.accessKey,
14+
secretKey: config.minio.secretKey
15+
})
16+
17+
exports.uploadImage = function (imagePath, callback) {
18+
if (!imagePath || typeof imagePath !== 'string') {
19+
callback(new Error('Image path is missing or wrong'), null)
20+
return
21+
}
22+
23+
if (!callback || typeof callback !== 'function') {
24+
callback(new Error('Callback has to be a function'), null)
25+
return
26+
}
27+
28+
fs.readFile(imagePath, function (err, buffer) {
29+
if (err) {
30+
callback(new Error(err), null)
31+
return
32+
}
33+
34+
let key = path.join('uploads', path.basename(imagePath))
35+
let protocol = config.minio.secure ? 'https' : 'http'
36+
37+
minioClient.putObject(config.s3bucket, key, buffer, buffer.size, getImageMimeType(imagePath), function (err, data) {
38+
if (err) {
39+
callback(new Error(err), null)
40+
return
41+
}
42+
callback(null, `${protocol}://${config.minio.endPoint}:${config.minio.port}/${config.s3bucket}/${key}`)
43+
})
44+
})
45+
}

lib/web/imageRouter/s3.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
'use strict'
2+
const fs = require('fs')
3+
const path = require('path')
4+
5+
const config = require('../../config')
6+
const {getImageMimeType} = require('../../utils')
7+
8+
const AWS = require('aws-sdk')
9+
const awsConfig = new AWS.Config(config.s3)
10+
const s3 = new AWS.S3(awsConfig)
11+
12+
exports.uploadImage = function (imagePath, callback) {
13+
if (!imagePath || typeof imagePath !== 'string') {
14+
callback(new Error('Image path is missing or wrong'), null)
15+
return
16+
}
17+
18+
if (!callback || typeof callback !== 'function') {
19+
callback(new Error('Callback has to be a function'), null)
20+
return
21+
}
22+
23+
fs.readFile(imagePath, function (err, buffer) {
24+
if (err) {
25+
callback(new Error(err), null)
26+
return
27+
}
28+
let params = {
29+
Bucket: config.s3bucket,
30+
Key: path.join('uploads', path.basename(imagePath)),
31+
Body: buffer
32+
}
33+
34+
const mimeType = getImageMimeType(imagePath)
35+
if (mimeType) { params.ContentType = mimeType }
36+
37+
s3.putObject(params, function (err, data) {
38+
if (err) {
39+
callback(new Error(err), null)
40+
return
41+
}
42+
43+
let s3Endpoint = 's3.amazonaws.com'
44+
if (config.s3.region && config.s3.region !== 'us-east-1') {
45+
s3Endpoint = `s3-${config.s3.region}.amazonaws.com`
46+
}
47+
callback(null, `https://${s3Endpoint}/${config.s3bucket}/${params.Key}`)
48+
})
49+
})
50+
}

0 commit comments

Comments
 (0)