Skip to content

Commit bd3d495

Browse files
authored
Merge pull request #248 from hackmdio/file-upload-options
Support other options for image uploading
2 parents 76a6190 + 1a4f395 commit bd3d495

14 files changed

Lines changed: 205 additions & 20 deletions

File tree

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ public/js/config.js
2525
# ignore webpack build
2626
public/build
2727
public/views/build
28+
29+
public/uploads/*
30+
!public/uploads/.gitkeep

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ Environment variables (will overwrite other server configs)
131131
| HMD_GOOGLE_CLIENTID | no example | Google API client id |
132132
| HMD_GOOGLE_CLIENTSECRET | no example | Google API client secret |
133133
| HMD_IMGUR_CLIENTID | no example | Imgur API client id |
134+
| HMD_IMAGE_UPLOAD_TYPE | `imgur`, `s3` or `filesystem` | Where to upload image. For S3, see our [S3 Image Upload Guide](docs/guides/s3-image-upload.md) |
135+
| HMD_S3_ACCESS_KEY_ID | no example | AWS access key id |
136+
| HMD_S3_SECRET_ACCESS_KEY | no example | AWS secret key |
137+
| HMD_S3_REGION | `ap-northeast-1` | AWS S3 region |
138+
| HMD_S3_BUCKET | no example | AWS S3 bucket name |
134139

135140
Server settings `config.json`
136141
---
@@ -166,6 +171,8 @@ Server settings `config.json`
166171
| heartbeatinterval | `5000` | socket.io heartbeat interval |
167172
| heartbeattimeout | `10000` | socket.io heartbeat timeout |
168173
| documentmaxlength | `100000` | note max length |
174+
| imageUploadType | `imgur`(default), `s3` or `filesystem` | Where to upload image
175+
| s3 | `{ "accessKeyId": "YOUR_S3_ACCESS_KEY_ID", "secretAccessKey": "YOUR_S3_ACCESS_KEY", "region": "YOUR_S3_REGION", "bucket": "YOUR_S3_BUCKET_NAME" }` | When `imageUploadType` be setted to `s3`, you would also need to setup this key, check our [S3 Image Upload Guide](docs/guides/s3-image-upload.md) |
169176

170177
Third-party integration api key settings
171178
---

app.js

Lines changed: 87 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -406,33 +406,102 @@ app.get('/me', function (req, res) {
406406
});
407407
}
408408
});
409-
//upload to imgur
409+
410+
//upload image
410411
app.post('/uploadimage', function (req, res) {
411412
var form = new formidable.IncomingForm();
413+
414+
form.keepExtensions = true;
415+
416+
if (config.imageUploadType === 'filesystem') {
417+
form.uploadDir = "public/uploads";
418+
}
419+
420+
function preprocessImage(path) {
421+
return new Promise((resolve) => {
422+
var oldFile = `${path}-old`;
423+
fs.rename(path, oldFile, function() {
424+
var sharp = require('sharp');
425+
sharp(oldFile).toFile(path).then(() => {
426+
fs.unlink(oldFile, function() {
427+
resolve(path);
428+
})
429+
});
430+
});
431+
});
432+
}
433+
412434
form.parse(req, function (err, fields, files) {
413435
if (err || !files.image || !files.image.path) {
414436
response.errorForbidden(res);
415437
} else {
416-
if (config.debug)
417-
logger.info('SERVER received uploadimage: ' + JSON.stringify(files.image));
418-
imgur.setClientId(config.imgur.clientID);
419-
try {
420-
imgur.uploadFile(files.image.path)
421-
.then(function (json) {
422-
if (config.debug)
423-
logger.info('SERVER uploadimage success: ' + JSON.stringify(json));
438+
preprocessImage(files.image.path).then(() => {
439+
if (config.debug)
440+
logger.info('SERVER received uploadimage: ' + JSON.stringify(files.image));
441+
442+
var path = require('path');
443+
try {
444+
switch (config.imageUploadType) {
445+
case 'filesystem':
424446
res.send({
425-
link: json.data.link.replace(/^http:\/\//i, 'https://')
447+
link: path.join(config.serverurl, files.image.path.match(/^public(.+$)/)[1])
426448
});
427-
})
428-
.catch(function (err) {
429-
logger.error(err);
430-
return res.status(500).end('upload image error');
431-
});
432-
} catch (err) {
449+
450+
break;
451+
452+
case 's3':
453+
var AWS = require('aws-sdk');
454+
var awsConfig = new AWS.Config(config.s3);
455+
var s3 = new AWS.S3(awsConfig);
456+
457+
fs.readFile(files.image.path, function (err, buffer) {
458+
var params = {
459+
Bucket: 'hackmd',
460+
Key: path.join('uploads', path.basename(files.image.path)),
461+
Body: buffer
462+
};
463+
464+
s3.putObject(params, function (err, data) {
465+
if (err) {
466+
logger.error(err);
467+
res.status(500).end('upload image error');
468+
} else {
469+
res.send({
470+
link: `https://s3-${config.s3.region}.amazonaws.com/${config.s3bucket}/${params.Key}`
471+
});
472+
}
473+
});
474+
475+
});
476+
477+
break;
478+
479+
case 'imgur':
480+
default:
481+
imgur.setClientId(config.imgur.clientID);
482+
imgur.uploadFile(files.image.path)
483+
.then(function (json) {
484+
if (config.debug)
485+
logger.info('SERVER uploadimage success: ' + JSON.stringify(json));
486+
res.send({
487+
link: json.data.link.replace(/^http:\/\//i, 'https://')
488+
});
489+
})
490+
.catch(function (err) {
491+
logger.error(err);
492+
return res.status(500).end('upload image error');
493+
});
494+
break;
495+
}
496+
} catch (err) {
497+
logger.error(err);
498+
return res.status(500).end('upload image error');
499+
}
500+
501+
}).catch((err) => {
433502
logger.error(err);
434-
return res.status(500).end('upload image error');
435-
}
503+
return res.status(500).end('process image error');
504+
});
436505
}
437506
});
438507
});

app.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,5 +107,13 @@
107107
},
108108
"addons": [
109109
"heroku-postgresql"
110+
],
111+
"buildpacks": [
112+
{
113+
"url": "https://github.com/alex88/heroku-buildpack-vips"
114+
},
115+
{
116+
"url": "https://github.com/heroku/heroku-buildpack-nodejs"
117+
}
110118
]
111119
}
53.4 KB
Loading
70.1 KB
Loading
68.6 KB
Loading
54.5 KB
Loading
89.4 KB
Loading
97.7 KB
Loading

0 commit comments

Comments
 (0)