apps: make downloadFile async
This commit is contained in:
118
src/apps.js
118
src/apps.js
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user