Skip to content

Commit 7f6c30f

Browse files
authored
Merge pull request #4 from vibhasfl/feature/s3fileupload
Flexible fileupload to disk and s3
2 parents bdccde9 + 6c41953 commit 7f6c30f

File tree

6 files changed

+45
-9
lines changed

6 files changed

+45
-9
lines changed

.env.sample

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,9 @@ MYSQL_PASSWORD='root'
1313
MYSQL_DATABASE='testdb'
1414
USE_MONGODB='true'
1515
USE_MYSQL='true'
16-
FILE_UPLOAD_SIZE_IN_BYTES=1000000
16+
FILE_UPLOAD_SIZE_IN_BYTES=1000000
17+
18+
AWS_S3_BUCKET=''
19+
AWS_S3_FILE_UPLOAD_KEY=''
20+
AWS_S3_ACCESS_KEY=''
21+
AWS_S3_SECRET_KEY=''

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Nodejs boilerplate with express,Mongoose,Mysql,JWT,ES6,ES7,ES8 support to develo
2828
- uses [helmet](https://github.com/helmetjs/helmet) to secure api endpoints which adds necessary security headers
2929
- Added support for databases like [mysql](https://github.com/mysqljs/mysql) and [mongoDB](https://github.com/Automattic/mongoose) with
3030
async await
31-
- Fileupload using [multer](https://github.com/expressjs/multer)
31+
- Flexible fileupload with disk and S3 storage using [multer](https://github.com/expressjs/multer) and [multer-s3](https://github.com/badunk/multer-s3)
3232
## Getting Started
3333
1. Clone repository
3434
```

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"main": "index.js",
66
"private": false,
77
"dependencies": {
8+
"aws-sdk": "^2.481.0",
89
"bcrypt": "^3.0.4",
910
"body-parser": "^1.18.3",
1011
"debug": "^4.1.1",
@@ -16,6 +17,7 @@
1617
"jsonwebtoken": "^8.4.0",
1718
"mongoose": "^5.4.10",
1819
"multer": "^1.4.1",
20+
"multer-s3": "^2.9.0",
1921
"mysql": "^2.16.0"
2022
},
2123
"devDependencies": {

server/app.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ const app = express()
1414

1515
app.use(bodyParser.json())
1616
app.use(helmet())
17-
app.use('/api', jwt({ secret: secretCallback }).unless({ path: [ '/api/health-check', '/api/users', '/api/auth/login', '/api/users/testmysqlroute', '/api/fileupload' ], requestProperty: 'auth' }))
17+
app.use(
18+
'/api',
19+
jwt({ secret: secretCallback }).unless({
20+
path: [ '/api/health-check', '/api/users', '/api/auth/login', '/api/users/testmysqlroute', '/api/fileupload', '/api/s3fileupload' ],
21+
requestProperty: 'auth'
22+
})
23+
)
1824
app.use('/api', Router)
1925

2026
// Handle 404

server/config/routes.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import express from 'express'
2+
import multer from 'multer'
23
import { userRoutes } from '../modules/users/user.routes'
34
import { authRoutes } from '../modules/auth/auth.routes'
4-
import { upload } from '../utils/upload'
55
import { httpStatus } from '../utils/httpStatus'
6+
import { diskStorage, limits, s3Storage, imageFileFilter } from '../utils/fileupload'
67
const Router = express.Router()
78

89
Router.all('/health-check', (req, res) => res.json({ message: 'OK' }))
910
Router.use('/users', userRoutes)
1011
Router.use('/auth', authRoutes)
1112

12-
Router.post('/fileupload', upload.single('avatar'), (req, res) => {
13+
Router.post('/fileupload', multer({ storage: diskStorage, limits, fileFilter: imageFileFilter }).single('avatar'), (req, res) => {
14+
if (!req.file) return res.status(httpStatus.UNPROCESSABLE_ENTITY).json({ error: 'Please select file' })
15+
return res.json({ data: req.file })
16+
})
17+
18+
Router.post('/s3fileupload', multer({ storage: s3Storage, limits, fileFilter: imageFileFilter }).single('avatar'), (req, res) => {
1319
if (!req.file) return res.status(httpStatus.UNPROCESSABLE_ENTITY).json({ error: 'Please select file' })
1420
return res.json({ data: req.file })
1521
})

server/utils/upload.js renamed to server/utils/fileupload.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
import multer from 'multer'
22
import crypto from 'crypto'
3+
import aws from 'aws-sdk'
4+
import multerS3 from 'multer-s3'
35
import { AppError } from './appError'
46
import { httpStatus } from './httpStatus'
57

6-
// Ref : https://www.npmjs.com/package/multer
8+
aws.config.update({ accessKeyId: process.env.AWS_S3_ACCESS_KEY, secretAccessKey: process.env.AWS_S3_SECRET_KEY })
9+
const s3 = new aws.S3()
710

8-
const storage = multer.diskStorage({
11+
const diskStorage = multer.diskStorage({
912
// Note : You can set your own upload path Ref : https://www.npmjs.com/package/multer#diskstorage
1013
// destination: function (req, file, cb) {},
1114
filename: function (req, file, cb) {
@@ -18,11 +21,25 @@ const storage = multer.diskStorage({
1821

1922
const limits = { fileSize: parseInt(process.env.FILE_UPLOAD_SIZE_IN_BYTES) || 1000000 }
2023

21-
const fileFilter = function (req, file, cb) {
24+
const imageFileFilter = function (req, file, cb) {
2225
if (![ 'image/png', 'image/jpg', 'image/jpeg' ].includes(file.mimetype)) {
2326
return cb(new AppError('Only jpg,jpeg,png formats are allowed', httpStatus.UNPROCESSABLE_ENTITY))
2427
}
2528
cb(null, true)
2629
}
2730

28-
export const upload = multer({ storage, limits, fileFilter })
31+
const s3Storage = multerS3({
32+
s3: s3,
33+
bucket: process.env.AWS_S3_BUCKET,
34+
metadata: function (req, file, cb) {
35+
cb(null, { fieldName: file.fieldname })
36+
},
37+
key: function (req, file, cb) {
38+
return crypto.randomBytes(16, function (err, raw) {
39+
if (err) cb(err)
40+
cb(null, process.env.AWS_S3_FILE_UPLOAD_KEY + raw.toString('hex') + Date.now() + '.' + file.originalname.split('.').pop().trim())
41+
})
42+
}
43+
})
44+
45+
export { diskStorage, limits, imageFileFilter, s3Storage }

0 commit comments

Comments
 (0)