apps: make downloadFile async

This commit is contained in:
Girish Ramakrishnan
2021-10-21 15:25:15 -07:00
parent 2e3070a5c6
commit 010024dfd7
2 changed files with 72 additions and 68 deletions

View File

@@ -2455,70 +2455,74 @@ async function listEventlog(app, page, perPage) {
return await eventlog.listPaged(actions, search, page, perPage);
}
function downloadFile(app, filePath, callback) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof filePath, 'string');
assert.strictEqual(typeof callback, 'function');
exec(app, { cmd: [ 'stat', '--printf=%F-%s', filePath ], tty: true }, function (error, stream) {
if (error) return callback(error);
var data = '';
async function drainStream(stream) {
return new Promise((resolve, reject) => {
let data = '';
stream.setEncoding('utf8');
stream.on('error', (error) => reject(new BoxError.FS_ERROR, error.message));
stream.on('data', function (d) { data += d; });
stream.on('end', function () {
var parts = data.split('-');
if (parts.length !== 2) return callback(new BoxError(BoxError.NOT_FOUND, 'file does not exist'));
var type = parts[0], filename, cmd, size;
if (type === 'regular file') {
cmd = [ 'cat', filePath ];
size = parseInt(parts[1], 10);
filename = path.basename(filePath);
if (isNaN(size)) return callback(new BoxError(BoxError.NOT_FOUND, 'file does not exist'));
} else if (type === 'directory') {
cmd = ['tar', 'zcf', '-', '-C', filePath, '.'];
filename = path.basename(filePath) + '.tar.gz';
size = 0; // unknown
} else {
return callback(new BoxError(BoxError.NOT_FOUND, 'only files or dirs can be downloaded'));
}
exec(app, { cmd: cmd , tty: false }, function (error, stream) {
if (error) return callback(error);
var stdoutStream = new TransformStream({
transform: function (chunk, ignoredEncoding, callback) {
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
for (;;) {
if (this._buffer.length < 8) break; // header is 8 bytes
var type = this._buffer.readUInt8(0);
var len = this._buffer.readUInt32BE(4);
if (this._buffer.length < (8 + len)) break; // not enough
var payload = this._buffer.slice(8, 8 + len);
this._buffer = this._buffer.slice(8+len); // consumed
if (type === 1) this.push(payload);
}
callback();
}
});
stream.pipe(stdoutStream);
callback(null, stdoutStream, { filename: filename, size: size });
});
resolve(data);
});
});
}
async function downloadFile(app, filePath) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof filePath, 'string');
const statStream = await exec(app, { cmd: [ 'stat', '--printf=%F-%s', filePath ], tty: true });
const data = await drainStream(statStream);
const parts = data.split('-');
if (parts.length !== 2) throw new BoxError(BoxError.NOT_FOUND, 'file does not exist');
let type = parts[0], filename, cmd, size;
if (type === 'regular file') {
cmd = [ 'cat', filePath ];
size = parseInt(parts[1], 10);
filename = path.basename(filePath);
if (isNaN(size)) throw new BoxError(BoxError.NOT_FOUND, 'file does not exist');
} else if (type === 'directory') {
cmd = ['tar', 'zcf', '-', '-C', filePath, '.'];
filename = path.basename(filePath) + '.tar.gz';
size = 0; // unknown
} else {
throw new BoxError(BoxError.NOT_FOUND, 'only files or dirs can be downloaded');
}
const inputStream = await exec(app, { cmd, tty: false });
// transforms the docker stream into a normal stream
const stdoutStream = new TransformStream({
transform: function (chunk, ignoredEncoding, callback) {
this._buffer = this._buffer ? Buffer.concat([this._buffer, chunk]) : chunk;
for (;;) {
if (this._buffer.length < 8) break; // header is 8 bytes
var type = this._buffer.readUInt8(0);
var len = this._buffer.readUInt32BE(4);
if (this._buffer.length < (8 + len)) break; // not enough
var payload = this._buffer.slice(8, 8 + len);
this._buffer = this._buffer.slice(8+len); // consumed
if (type === 1) this.push(payload);
}
callback();
}
});
inputStream.pipe(stdoutStream);
return { stream: stdoutStream, filename, size };
}
async function uploadFile(app, sourceFilePath, destFilePath) {
assert.strictEqual(typeof app, 'object');
assert.strictEqual(typeof sourceFilePath, 'string');