-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathhandler.js
138 lines (113 loc) · 3.41 KB
/
handler.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
'use strict';
const Fs = require('fs');
const Boom = require('boom');
const Path = require('path');
const FsExtra = require('fs-extra');
const Magic = require('mmmagic');
const Sharp = require('sharp');
const Hoek = require('hoek');
const MimeMagic = new Magic.Magic(Magic.MAGIC_MIME_TYPE);
const Joi = require('joi');
module.exports = function(options) {
return function(request, reply) {
try {
FsExtra.mkdirsSync(options.store);
const keys = Object.keys(request.payload);
const fileObj = request.payload[keys[0]];
const destPath = Path.resolve(Path.join(options.store, fileObj.hapi.filename));
const fileStream = Fs.createWriteStream(destPath);
fileStream.on('finish', async function () {
const info = { filename: fileObj.hapi.filename, path: destPath };
info.mime = await getMime(destPath);
if (options.imageProcessing) {
const result = await processImage({ filename: fileObj.hapi.filename, path: destPath, mime: info.mime }, require(Path.resolve(options.imageProcessing)));
if (result.meta) {
info.meta = result.meta;
}
}
info.size = Fs.statSync(destPath).size;
console.log(`Saved file: "${destPath}"`);
return reply(info);
});
fileObj.pipe(fileStream);
} catch (err) {
console.log(err);
return reply(Boom.badRequest(err));
}
};
};
function processImage(file, config) {
return new Promise(async function(resolve) {
validateImageConfig(config);
const output = {};
if ([ 'image/jpeg', 'image/png' ].indexOf(file.mime) === -1) {
return resolve({});
}
if (config.resize) {
await resize(file, config);
}
if (config.thumbnails) {
await thumbs(file, config);
}
if (config.meta) {
const meta = await Sharp(file.path).metadata();
output.meta = meta;
}
return resolve(output);
});
}
function thumbs(file, config) {
const imgPromises = [];
for (let i = 0; i < config.thumbnails.length; i++) {
const size = config.thumbnails[i];
const thumbPath = Path.join(Path.dirname(file.path), size.toString());
FsExtra.mkdirsSync(thumbPath);
imgPromises.push(
Sharp(file.path)
.resize(null, size)
.max()
.toFile(Path.join(thumbPath, file.filename))
);
}
return Promise.all(imgPromises);
}
function resize(file, config) {
return new Promise((resolve, reject) => {
Sharp(file.path)
.resize(config.resize.maxWidth, config.resize.maxHeight)
.withoutEnlargement()
.max()
.toBuffer(function(err, outputBuffer) {
if (err) {
throw err;
}
const tmpPath = Hoek.uniqueFilename(Path.dirname(file.path), Path.extname(file.filename).toLowerCase());
Fs.writeFile(file.path, outputBuffer, function(err) {
if (err) throw err;
return resolve();
});
});
});
}
function validateImageConfig(config) {
Joi.assert(config, Joi.object({
resize: Joi.object({
maxWidth: Joi.number().required(),
maxHeight: Joi.number().required()
}),
thumbnails: Joi.array().items(
Joi.number().required()
),
meta: Joi.boolean()
}));
}
function getMime(path) {
return new Promise((resolve, reject) => {
MimeMagic.detectFile(path, function(err, result) {
if (err) {
return reject(err);
}
return resolve(result);
});
});
}