uploader.js
6.06 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/**
* 处理路由的文件上传action
*/
/* global global */
/* global process */
"use strict";
module.exports = function Uploader(routerPath, db) {
routerPath = routerPath || '';
const _ = require('lodash'),
path = require('path'),
fs = require('fs'),
Formidable = require('formidable'),
gm = require('gm'),
express = require('express'),
router = express.Router(),
config_path = global.config.path,
UPLOAD_OPTION = global.config.upload,
ENTITIES_PATH = config_path.ENTITIES_PATH,
logger = global.loggers.upload,
crypto_utils = require('kml-crypto-utils'),
Result = require('kml-express-stage/lib/result');
const
DEST_DIR = path.resolve(UPLOAD_OPTION.root, routerPath),
IMAGE_URL = UPLOAD_OPTION.base_url||'/' + routerPath + '/',
THUMB_WIDTH = 240;
//定义上传文件的访问路径
router.use(`/${routerPath}`, express.static(DEST_DIR));
// var FileInfo = db.import(path.resolve(ENTITIES_PATH, 'file_info'));
var upload_root = path.resolve(UPLOAD_OPTION.root);
if (!fs.existsSync(upload_root)) {
fs.mkdir(upload_root);
}
if (!fs.existsSync(DEST_DIR)) {
fs.mkdir(DEST_DIR);
}
let fn_request = function (req, res, next) {
/**
* 创建缩略图
* @param gm_object gm对象,可以在此前对图片做好预处理
* @param file_orig 原始处理图片文件
* @param uploaded_file 上传文件结构
*/
var create_thumb = function (gm_object, file_orig, uploaded_file) {
let dest_thumb = uploaded_file.thumb_path, //缩略图
dest_file = uploaded_file.file_path, //优化后的图片
dest_orig = uploaded_file.orig_path; //原始图片
gm_object.size(function (err, size) {
if (err) {
logger.error(err, uploaded_file);
return;
}
this.write(dest_file, function (err) {
if (err) {
logger.error(err, uploaded_file);
} else {
let thumb_w = size.width > size.height ? size.height : size.width; //计算最小边作为缩略图
thumb_w = thumb_w > THUMB_WIDTH ? THUMB_WIDTH : thumb_w;
gm(dest_file).thumb(thumb_w, thumb_w, dest_thumb, 0, 'center', function (err) {
err ? logger.error(err, uploaded_file) : logger.debug('image saved to', uploaded_file);
//move file to dest_orig
fs.rename(file_orig.path, dest_orig);
});
}
})
});
};
// parse a file upload
let form = new Formidable.IncomingForm();
form.encoding = 'utf-8';
form.uploadDir = DEST_DIR;
form.hash = 'md5';
form.keepExtensions = true;
form.maxFieldsSize = 10*(1<<20); //max file size is 10M
// 处理上传文件
form.parse(req, function (err, fields, files) {
let uploaded_files = [];
if (files) {
for (let key in files) {
if (files.hasOwnProperty(key)) {
let file = files[key];
if (file && file.size) {
let file_ext = file.type.replace('image/', ''), orig_ext = file_ext;
switch (file.type) {
case 'image/gif':
file_ext = 'gif';
break;
case 'image/jpeg':
file_ext = 'jpg';
break;
case 'image/png':
file_ext = 'png';
break;
default:
res.json(new Result(Result.ERROR, '上传文件格式错误'));
return null;
}
let regexp = /\.([\w]{3,})$/,
salt = (~~(Math.random() * 1000000000)).toString(36),
file_id = crypto_utils.UUID(),
file_name = `${file_id}_${salt}.${file_ext}`,
orig_file_name = `${file_id}_${salt}_o.${orig_ext}`,
dest_file = path.resolve(DEST_DIR, file_name),
dest_orig = path.resolve(DEST_DIR, orig_file_name),
dest_thumb = dest_file.replace(regexp, '_s.$1'),
uploaded_file = {
id: file_id,
content_type: file.type,
name: file.name,
size: file.size,
file_path: dest_file,
thumb_path: dest_thumb,
orig_path: dest_orig,
hash: file.hash,
url: IMAGE_URL + file_name,
params: fields,
key: key,
thumbnail: IMAGE_URL + file_name.replace(regexp, '_s.$1')
};
switch (file.type) {
case 'image/gif':
create_thumb(gm(file.path + '[0]'), file, uploaded_file);
break;
case 'image/jpeg':
case 'image/png':
create_thumb(gm(file.path).autoOrient(), file, uploaded_file);
break;
default:
fs.unlink(file.path);
logger.error(`${file.name} is not jpg/png/gif but ${file.type}`);
break;
}
uploaded_files.push(uploaded_file);
}
}
}
}
//处理结果
if (uploaded_files.length) {
// FileInfo.bulkCreate(uploaded_files)
// .then(function (files) {
logger.debug('file saved into db', files);
// })
}
//输出结果
res.json(new Result(Result.OK, undefined, undefined, {files: uploaded_files}));
next && next();
return null;
});
};
var upload_regex = /^\/(.+\/)*upload$/;
router.post(upload_regex, fn_request);
router.get(upload_regex, function (req, res, next) {
res.writeHead(200, {'content-type': 'text/html'});
res.end('\
<article>\
<form action="" enctype="multipart/form-data" method="post">\
<input type="text" name="title" placeholder="图片简介" style="width: 100%;"><br>\
<input type="file" name="upload" multiple="multiple" style="width: 50%;">\
<input type="submit" value="上传" style="width: 30%;">\
</form>\
</article>'
);
next && next();
});
return router;
};