diff --git a/src/apps.js b/src/apps.js index 9e4cb01ea..0cd547e54 100644 --- a/src/apps.js +++ b/src/apps.js @@ -1136,10 +1136,28 @@ function downloadFile(appId, filePath, callback) { assert.strictEqual(typeof callback, 'function'); var filename = path.basename(filePath); - exec(appId, { cmd: ['cat', filePath ], tty: false }, function (error, stream) { + exec(appId, { cmd: [ 'stat', '--printf=%F-%s', filePath ], tty: true }, function (error, stream) { if (error) return callback(error); - return callback(null, stream, filename); + var data = ''; + stream.setEncoding('utf8'); + stream.on('data', function (d) { data += d; }); + stream.on('end', function () { + var parts = data.split('-'); + if (parts.length !== 2) return callback(new AppsError(AppsError.NOT_FOUND, 'file does not exist')); + + var type = parts[0]; + if (type !== 'regular file') return callback(new AppsError(AppsError.NOT_FOUND, 'only files can be downloaded')); + + var size = parseInt(parts[1], 10); + if (isNaN(size)) return callback(new AppsError(AppsError.NOT_FOUND, 'file does not exist')); + + exec(appId, { cmd: [ 'cat', filePath ], tty: false }, function (error, stream) { + if (error) return callback(error); + + return callback(null, stream, { filename: filename, size: size }); + }); + }); }); } diff --git a/src/routes/apps.js b/src/routes/apps.js index 140250bca..417eed113 100644 --- a/src/routes/apps.js +++ b/src/routes/apps.js @@ -557,14 +557,15 @@ function downloadFile(req, res, next) { if (typeof req.query.file !== 'string' || !req.query.file) return next(new HttpError(400, 'file query argument must be provided')); - apps.downloadFile(req.params.id, req.query.file, function (error, result, filename) { + apps.downloadFile(req.params.id, req.query.file, function (error, result, info) { + if (error && error.reason === AppsError.NOT_FOUND) return next(new HttpError(404, error.message)); if (error) return next(new HttpError(500, error)); // TODO get real content type and size res.writeHead(200, { 'Content-Type': 'application/octet-stream', - 'Content-Disposition': 'attachment; filename="' + filename + '"' - // 'Content-Length': stat.size + 'Content-Disposition': 'attachment; filename="' + info.filename + '"', + 'Content-Length': info.size }); result.pipe(res);