2018-04-12 21:06:18 +00:00
|
|
|
import * as Koa from 'koa';
|
|
|
|
import * as send from 'koa-send';
|
|
|
|
import * as mongodb from 'mongodb';
|
2019-03-18 04:20:49 +00:00
|
|
|
import * as rename from 'rename';
|
2018-05-03 11:03:14 +00:00
|
|
|
import DriveFile, { getDriveFileBucket } from '../../models/drive-file';
|
|
|
|
import DriveFileThumbnail, { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
|
2018-11-25 19:25:48 +00:00
|
|
|
import DriveFileWebpublic, { getDriveFileWebpublicBucket } from '../../models/drive-file-webpublic';
|
2019-02-03 09:16:57 +00:00
|
|
|
import { serverLogger } from '..';
|
2019-03-18 06:23:45 +00:00
|
|
|
import { contentDisposition } from '../../misc/content-disposition';
|
2018-05-03 11:03:14 +00:00
|
|
|
|
2018-05-04 08:59:51 +00:00
|
|
|
const assets = `${__dirname}/../../server/file/assets/`;
|
|
|
|
|
2019-01-22 12:42:05 +00:00
|
|
|
const commonReadableHandlerGenerator = (ctx: Koa.BaseContext) => (e: Error): void => {
|
2019-02-03 09:16:57 +00:00
|
|
|
serverLogger.error(e);
|
2018-05-03 11:03:14 +00:00
|
|
|
ctx.status = 500;
|
|
|
|
};
|
2018-04-12 21:06:18 +00:00
|
|
|
|
2019-01-22 12:42:05 +00:00
|
|
|
export default async function(ctx: Koa.BaseContext) {
|
2018-04-12 21:06:18 +00:00
|
|
|
// Validate id
|
|
|
|
if (!mongodb.ObjectID.isValid(ctx.params.id)) {
|
|
|
|
ctx.throw(400, 'incorrect id');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const fileId = new mongodb.ObjectID(ctx.params.id);
|
|
|
|
|
|
|
|
// Fetch drive file
|
|
|
|
const file = await DriveFile.findOne({ _id: fileId });
|
|
|
|
|
|
|
|
if (file == null) {
|
|
|
|
ctx.status = 404;
|
2019-01-22 12:42:05 +00:00
|
|
|
await send(ctx as any, '/dummy.png', { root: assets });
|
2018-04-12 21:06:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-17 11:04:19 +00:00
|
|
|
if (file.metadata.deletedAt) {
|
|
|
|
ctx.status = 410;
|
2019-01-22 12:42:05 +00:00
|
|
|
await send(ctx as any, '/tombstone.png', { root: assets });
|
2018-05-25 11:19:14 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-07-23 20:04:43 +00:00
|
|
|
if (file.metadata.withoutChunks) {
|
2018-05-25 11:19:14 +00:00
|
|
|
ctx.status = 204;
|
2018-04-17 11:04:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-03 11:12:08 +00:00
|
|
|
const sendRaw = async () => {
|
2018-11-25 19:25:48 +00:00
|
|
|
if (file.metadata && file.metadata.accessKey && file.metadata.accessKey != ctx.query['original']) {
|
|
|
|
ctx.status = 403;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-03 11:12:08 +00:00
|
|
|
const bucket = await getDriveFileBucket();
|
|
|
|
const readable = bucket.openDownloadStream(fileId);
|
|
|
|
readable.on('error', commonReadableHandlerGenerator(ctx));
|
|
|
|
ctx.set('Content-Type', file.contentType);
|
|
|
|
ctx.body = readable;
|
|
|
|
};
|
|
|
|
|
2018-05-03 11:03:14 +00:00
|
|
|
if ('thumbnail' in ctx.query) {
|
2018-08-15 22:17:04 +00:00
|
|
|
const thumb = await DriveFileThumbnail.findOne({
|
|
|
|
'metadata.originalId': fileId
|
|
|
|
});
|
|
|
|
|
|
|
|
if (thumb != null) {
|
|
|
|
ctx.set('Content-Type', 'image/jpeg');
|
2019-03-18 06:23:45 +00:00
|
|
|
ctx.set('Content-Disposition', contentDisposition('inline', `${rename(file.filename, { suffix: '-thumb', extname: '.jpeg' })}"`));
|
2018-08-15 22:17:04 +00:00
|
|
|
const bucket = await getDriveFileThumbnailBucket();
|
|
|
|
ctx.body = bucket.openDownloadStream(thumb._id);
|
2018-05-03 11:03:14 +00:00
|
|
|
} else {
|
2019-02-02 04:22:09 +00:00
|
|
|
if (file.contentType.startsWith('image/')) {
|
2019-03-18 06:23:45 +00:00
|
|
|
ctx.set('Content-Disposition', contentDisposition('inline', `${file.filename}"`));
|
2019-02-02 04:22:09 +00:00
|
|
|
await sendRaw();
|
|
|
|
} else {
|
|
|
|
ctx.status = 404;
|
|
|
|
await send(ctx as any, '/dummy.png', { root: assets });
|
|
|
|
}
|
2018-05-03 11:03:14 +00:00
|
|
|
}
|
2018-11-25 19:25:48 +00:00
|
|
|
} else if ('web' in ctx.query) {
|
|
|
|
const web = await DriveFileWebpublic.findOne({
|
|
|
|
'metadata.originalId': fileId
|
|
|
|
});
|
|
|
|
|
|
|
|
if (web != null) {
|
|
|
|
ctx.set('Content-Type', file.contentType);
|
2019-03-18 06:23:45 +00:00
|
|
|
ctx.set('Content-Disposition', contentDisposition('inline', `${rename(file.filename, { suffix: '-web' })}"`));
|
2018-11-25 19:25:48 +00:00
|
|
|
|
|
|
|
const bucket = await getDriveFileWebpublicBucket();
|
|
|
|
ctx.body = bucket.openDownloadStream(web._id);
|
|
|
|
} else {
|
2019-03-18 06:23:45 +00:00
|
|
|
ctx.set('Content-Disposition', contentDisposition('inline', `${file.filename}"`));
|
2018-11-25 19:25:48 +00:00
|
|
|
await sendRaw();
|
|
|
|
}
|
2018-05-03 11:03:14 +00:00
|
|
|
} else {
|
|
|
|
if ('download' in ctx.query) {
|
2019-03-18 06:23:45 +00:00
|
|
|
ctx.set('Content-Disposition', contentDisposition('attachment', `${file.filename}`));
|
2018-05-03 11:03:14 +00:00
|
|
|
}
|
2018-04-12 21:06:18 +00:00
|
|
|
|
2018-05-03 11:12:08 +00:00
|
|
|
await sendRaw();
|
2018-05-03 11:03:14 +00:00
|
|
|
}
|
2018-04-12 21:06:18 +00:00
|
|
|
}
|