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