Merge pull request #174 from strongloop/refactor-download
Refactor download
This commit is contained in:
commit
cb87b9cf94
|
@ -204,16 +204,6 @@ exports.upload = function(provider, req, res, options, cb) {
|
|||
});
|
||||
};
|
||||
|
||||
function handleError(res, err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
res.type('application/json');
|
||||
res.status(404).send({error: err});
|
||||
return;
|
||||
}
|
||||
res.type('application/json');
|
||||
res.status(500).send({error: err});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle download from a container/file.
|
||||
* @param {Object} provider The storage service provider
|
||||
|
@ -233,57 +223,71 @@ exports.download = function(provider, req, res, container, file, cb) {
|
|||
|
||||
var range = null;
|
||||
|
||||
if (req) {
|
||||
if (req.headers) {
|
||||
range = req.headers.range || '';
|
||||
if (!req) {
|
||||
// TODO(rfeng/bajtos) We should let the caller now about the problem!
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.headers) {
|
||||
range = req.headers.range || '';
|
||||
}
|
||||
|
||||
if (!range) {
|
||||
return download(params);
|
||||
}
|
||||
|
||||
provider.getFile(params.container, params.remote, function(err, stats) {
|
||||
if (err) {
|
||||
return cb(processError(err, params.remote));
|
||||
}
|
||||
|
||||
if (range) {
|
||||
provider.getFile(params.container, params.remote, function(err, stats) {
|
||||
if (err) {
|
||||
handleError(res, err);
|
||||
} else {
|
||||
var total = stats.size;
|
||||
setupPartialDownload(params, stats, res);
|
||||
download(params);
|
||||
});
|
||||
|
||||
var parts = range.replace(/bytes=/, '').split('-');
|
||||
var partialstart = parts[0];
|
||||
var partialend = parts[1];
|
||||
function download(params) {
|
||||
var reader = provider.download(params);
|
||||
|
||||
params.start = parseInt(partialstart, 10);
|
||||
params.end = partialend ? parseInt(partialend, 10) : total - 1;
|
||||
res.type(fileName);
|
||||
|
||||
var chunksize = (params.end - params.start) + 1;
|
||||
reader.pipe(res);
|
||||
|
||||
res.status(206);
|
||||
res.set('Content-Range', 'bytes ' + params.start + '-' + params.end + '/' + total);
|
||||
res.set('Accept-Ranges', 'bytes');
|
||||
res.set('Content-Length', chunksize);
|
||||
reader.on('error', function onReaderError(err) {
|
||||
cb(processError(err, params.remote));
|
||||
cb = function() {}; // avoid double-callback
|
||||
});
|
||||
|
||||
var reader = provider.download(params);
|
||||
|
||||
res.type(fileName);
|
||||
|
||||
reader.pipe(res);
|
||||
reader.on('error', function(err) {
|
||||
handleError(res, err);
|
||||
});
|
||||
reader.on('end', function() {
|
||||
cb();
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var reader = provider.download(params);
|
||||
|
||||
res.type(fileName);
|
||||
|
||||
reader.pipe(res);
|
||||
reader.on('error', function(err) {
|
||||
handleError(res, err);
|
||||
});
|
||||
reader.on('end', function() {
|
||||
cb();
|
||||
});
|
||||
}
|
||||
reader.on('end', function onReaderEnd() {
|
||||
cb();
|
||||
cb = function() {}; // avoid double-callback
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function setupPartialDownload(params, stats, res) {
|
||||
var total = stats.size;
|
||||
|
||||
var parts = range.replace(/bytes=/, '').split('-');
|
||||
var partialstart = parts[0];
|
||||
var partialend = parts[1];
|
||||
|
||||
params.start = parseInt(partialstart, 10);
|
||||
params.end = partialend ? parseInt(partialend, 10) : total - 1;
|
||||
|
||||
var chunksize = (params.end - params.start) + 1;
|
||||
|
||||
res.status(206);
|
||||
res.set('Content-Range', 'bytes ' + params.start + '-' + params.end + '/' + total);
|
||||
res.set('Accept-Ranges', 'bytes');
|
||||
res.set('Content-Length', chunksize);
|
||||
};
|
||||
|
||||
function processError(err, fileName) {
|
||||
if (err.code === 'ENOENT') {
|
||||
err.statusCode = err.status = 404;
|
||||
// Hide the original message reported e.g. by FS provider, as it may
|
||||
// contain sensitive information.
|
||||
err.message = 'File not found: ' + fileName;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -314,6 +314,24 @@ describe('storage service', function() {
|
|||
});
|
||||
});
|
||||
|
||||
it('should run a function after a download failed', function(done) {
|
||||
var hookCalled = false;
|
||||
var Container = app.models.Container;
|
||||
|
||||
Container.afterRemoteError('download', function(ctx, cb) {
|
||||
hookCalled = true;
|
||||
cb();
|
||||
});
|
||||
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.get('/containers/album1/download/does-not-exist')
|
||||
.expect(404, function(err, res) {
|
||||
if (err) return done(err);
|
||||
assert(hookCalled, 'afterRemoteEror hook was not called');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete a file', function(done) {
|
||||
request('http://localhost:' + app.get('port'))
|
||||
.del('/containers/album1/files/test.jpg')
|
||||
|
|
Loading…
Reference in New Issue