Skip to content

Commit 7b14845

Browse files
authored
Merge pull request #1530 from hackmdio/fix/improve-filesystem-upload
fix: improve image upload to filesystem may caused app crash
2 parents c6b6d63 + 8b67d69 commit 7b14845

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

lib/imageRouter/filesystem.js

+44-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,39 @@
11
'use strict'
2+
3+
const crypto = require('crypto')
4+
const fs = require('fs')
25
const URL = require('url').URL
36
const path = require('path')
47

58
const config = require('../config')
69
const logger = require('../logger')
710

11+
/**
12+
* generate a random filename for uploaded image
13+
*/
14+
function randomFilename () {
15+
const buf = crypto.randomBytes(16)
16+
return `upload_${buf.toString('hex')}`
17+
}
18+
19+
/**
20+
* pick a filename not exist in filesystem
21+
* maximum attempt 5 times
22+
*/
23+
function pickFilename (defaultFilename) {
24+
let retryCounter = 5
25+
let filename = defaultFilename
26+
const extname = path.extname(defaultFilename)
27+
while (retryCounter-- > 0) {
28+
if (fs.existsSync(path.join(config.uploadsPath, filename))) {
29+
filename = `${randomFilename()}${extname}`
30+
continue
31+
}
32+
return filename
33+
}
34+
throw new Error('file exists.')
35+
}
36+
837
exports.uploadImage = function (imagePath, callback) {
938
if (!imagePath || typeof imagePath !== 'string') {
1039
callback(new Error('Image path is missing or wrong'), null)
@@ -16,11 +45,24 @@ exports.uploadImage = function (imagePath, callback) {
1645
return
1746
}
1847

48+
let filename = path.basename(imagePath)
49+
try {
50+
filename = pickFilename(path.basename(imagePath))
51+
} catch (e) {
52+
return callback(e, null)
53+
}
54+
55+
try {
56+
fs.copyFileSync(imagePath, path.join(config.uploadsPath, filename))
57+
} catch (e) {
58+
return callback(e, null)
59+
}
60+
1961
let url
2062
try {
21-
url = (new URL(path.basename(imagePath), config.serverURL + '/uploads/')).href
63+
url = (new URL(filename, config.serverURL + '/uploads/')).href
2264
} catch (e) {
23-
url = config.serverURL + '/uploads/' + path.basename(imagePath)
65+
url = config.serverURL + '/uploads/' + filename
2466
}
2567

2668
callback(null, url)

lib/imageRouter/index.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict'
22

3+
const fs = require('fs')
34
const Router = require('express').Router
45
const formidable = require('formidable')
56

@@ -15,10 +16,6 @@ imageRouter.post('/uploadimage', function (req, res) {
1516

1617
form.keepExtensions = true
1718

18-
if (config.imageUploadType === 'filesystem') {
19-
form.uploadDir = config.uploadsPath
20-
}
21-
2219
form.parse(req, function (err, fields, files) {
2320
if (err || !files.image || !files.image.path) {
2421
response.errorForbidden(req, res)
@@ -29,6 +26,8 @@ imageRouter.post('/uploadimage', function (req, res) {
2926

3027
const uploadProvider = require('./' + config.imageUploadType)
3128
uploadProvider.uploadImage(files.image.path, function (err, url) {
29+
// remove temporary upload file, and ignore any error
30+
fs.unlink(files.image.path, () => {})
3231
if (err !== null) {
3332
logger.error(err)
3433
return res.status(500).end('upload image error')

0 commit comments

Comments
 (0)