Skip to content

Commit b6acff5

Browse files
committed
merge aguidrevitch#46 reduce synchronous disk IO operations
2 parents 0bf2aef + 3135dec commit b6acff5

File tree

2 files changed

+83
-69
lines changed

2 files changed

+83
-69
lines changed

lib/uploadhandler.js

+81-68
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ var EventEmitter = require('events').EventEmitter,
44
formidable = require('formidable'),
55
imageMagick = require('imagemagick'),
66
mkdirp = require('mkdirp'),
7-
_ = require('lodash');
7+
_ = require('lodash'),
8+
async = require('async');
89

910
module.exports = function (options) {
1011

@@ -34,19 +35,24 @@ module.exports = function (options) {
3435
this.noCache();
3536
var files = [];
3637
fs.readdir(options.uploadDir(), _.bind(function (err, list) {
37-
_.each(list, function (name) {
38-
var stats = fs.statSync(options.uploadDir() + '/' + name),
39-
fileInfo;
40-
if (stats.isFile()) {
41-
fileInfo = new FileInfo({
42-
name: name,
43-
size: stats.size
44-
});
45-
this.initUrls(fileInfo);
46-
files.push(fileInfo);
47-
}
48-
}, this);
49-
this.callback({files: files});
38+
async.each(list, _.bind(function(name, cb) {
39+
fs.stat(options.uploadDir() + '/' + name, _.bind(function(err, stats) {
40+
if (!err && stats.isFile()) {
41+
var fileInfo = new FileInfo({
42+
name: name,
43+
size: stats.size
44+
});
45+
this.initUrls(fileInfo, function(err) {
46+
files.push(fileInfo);
47+
cb(err);
48+
});
49+
}
50+
else cb(err);
51+
}, this));
52+
}, this),
53+
_.bind(function(err) {
54+
this.callback({files: files});
55+
}, this));
5056
}, this));
5157
};
5258

@@ -60,12 +66,15 @@ module.exports = function (options) {
6066
redirect,
6167
finish = _.bind(function () {
6268
if (!--counter) {
63-
_.each(files, function (fileInfo) {
64-
this.initUrls(fileInfo);
65-
fileInfo = _.extend(fileInfo, self.req.fields);
66-
this.emit('end', fileInfo);
67-
}, this);
68-
this.callback({files: files}, redirect);
69+
async.each(files, _.bind(function(fileInfo, cb) {
70+
this.initUrls(fileInfo, _.bind(function(err) {
71+
this.emit('end', fileInfo);
72+
cb(err);
73+
}, this));
74+
}, this),
75+
_.bind(function(err) {
76+
this.callback({files: files}, redirect);
77+
}, this));
6978
}
7079
}, this);
7180

@@ -90,56 +99,58 @@ module.exports = function (options) {
9099
self.req.fields[name] = value;
91100
})
92101
.on('file', function (name, file) {
102+
counter++;
93103
var fileInfo = map[path.basename(file.path)];
94-
if (fs.existsSync(file.path)) {
95-
fileInfo.size = file.size;
96-
if (!fileInfo.validate()) {
97-
fs.unlink(file.path);
98-
return;
99-
}
100-
101-
var generatePreviews = function () {
102-
if (options.imageTypes.test(fileInfo.name)) {
103-
_.each(options.imageVersions, function (value, version) {
104-
// creating directory recursive
105-
if (!fs.existsSync(options.uploadDir() + '/' + version + '/'))
106-
mkdirp.sync(options.uploadDir() + '/' + version + '/');
107-
108-
counter++;
109-
var opts = options.imageVersions[version];
110-
imageMagick.resize({
111-
width: opts.width,
112-
height: opts.height,
113-
srcPath: options.uploadDir() + '/' + fileInfo.name,
114-
dstPath: options.uploadDir() + '/' + version + '/' + fileInfo.name,
115-
customArgs: opts.imageArgs || ['-auto-orient']
116-
}, finish);
117-
});
104+
fs.exists(file.path, function(exists) {
105+
if (exists) {
106+
fileInfo.size = file.size;
107+
if (!fileInfo.validate()) {
108+
fs.unlink(file.path);
109+
finish();
110+
return;
118111
}
119-
}
120112

121-
if (!fs.existsSync(options.uploadDir() + '/'))
122-
mkdirp.sync(options.uploadDir() + '/');
113+
var generatePreviews = function () {
114+
if (options.imageTypes.test(fileInfo.name)) {
115+
_.each(options.imageVersions, function (value, version) {
116+
counter++;
117+
// creating directory recursive
118+
mkdirp(options.uploadDir() + '/' + version + '/', function (err, made) {
119+
var opts = options.imageVersions[version];
120+
imageMagick.resize({
121+
width: opts.width,
122+
height: opts.height,
123+
srcPath: options.uploadDir() + '/' + fileInfo.name,
124+
dstPath: options.uploadDir() + '/' + version + '/' + fileInfo.name,
125+
customArgs: opts.imageArgs || ['-auto-orient']
126+
}, finish);
127+
});
128+
});
129+
}
130+
}
123131

124-
counter++;
125-
fs.rename(file.path, options.uploadDir() + '/' + fileInfo.name, function (err) {
126-
if (!err) {
127-
generatePreviews();
128-
finish();
129-
} else {
130-
var is = fs.createReadStream(file.path);
131-
var os = fs.createWriteStream(options.uploadDir() + '/' + fileInfo.name);
132-
is.on('end', function (err) {
132+
mkdirp(options.uploadDir() + '/', function(err, made) {
133+
fs.rename(file.path, options.uploadDir() + '/' + fileInfo.name, function (err) {
133134
if (!err) {
134-
fs.unlinkSync(file.path);
135135
generatePreviews();
136+
finish();
137+
} else {
138+
var is = fs.createReadStream(file.path);
139+
var os = fs.createWriteStream(options.uploadDir() + '/' + fileInfo.name);
140+
is.on('end', function (err) {
141+
if (!err) {
142+
fs.unlink(file.path);
143+
generatePreviews();
144+
}
145+
finish();
146+
});
147+
is.pipe(os);
136148
}
137-
finish();
138149
});
139-
is.pipe(os);
140-
}
141-
});
142-
}
150+
});
151+
}
152+
else finish();
153+
});
143154
})
144155
.on('aborted', function () {
145156
_.each(tmpFiles, function (file) {
@@ -172,15 +183,17 @@ module.exports = function (options) {
172183
});
173184
};
174185

175-
UploadHandler.prototype.initUrls = function (fileInfo) {
186+
UploadHandler.prototype.initUrls = function (fileInfo, cb) {
176187
var baseUrl = (options.ssl ? 'https:' : 'http:') + '//' + (options.hostname || this.req.get('Host'));
177188
fileInfo.setUrl(null, baseUrl + options.uploadUrl());
178189
fileInfo.setUrl('delete', baseUrl + this.req.originalUrl);
179-
_.each(options.imageVersions, function (value, version) {
180-
if (fs.existsSync(options.uploadDir() + '/' + version + '/' + fileInfo.name)) {
181-
fileInfo.setUrl(version, baseUrl + options.uploadUrl() + '/' + version);
182-
}
183-
}, this);
190+
async.each(Object.keys(options.imageVersions), function(version, cb) {
191+
fs.exists(options.uploadDir() + '/' + version + '/' + fileInfo.name, function(exists) {
192+
if (exists) fileInfo.setUrl(version, baseUrl + options.uploadUrl() + '/' + version);
193+
cb(null);
194+
})
195+
},
196+
cb);
184197
};
185198

186199
return UploadHandler;

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
"formidable": ">=1.0.11",
1414
"imagemagick": ">=0.1.2",
1515
"lodash": ">= 0.9.2",
16-
"mkdirp": ">= 0.3.4"
16+
"mkdirp": ">= 0.3.4",
17+
"async": "*"
1718
},
1819
"engines": {
1920
"node": ">= 0.8.8"

0 commit comments

Comments
 (0)