2018-05-03 11:03:14 +00:00
|
|
|
import * as fs from 'fs';
|
|
|
|
|
2018-04-12 21:06:18 +00:00
|
|
|
import * as Koa from 'koa';
|
|
|
|
import * as send from 'koa-send';
|
|
|
|
import * as mongodb from 'mongodb';
|
2018-05-03 11:03:14 +00:00
|
|
|
import DriveFile, { getDriveFileBucket } from '../../models/drive-file';
|
|
|
|
import DriveFileThumbnail, { getDriveFileThumbnailBucket } from '../../models/drive-file-thumbnail';
|
|
|
|
|
2018-05-04 08:59:51 +00:00
|
|
|
const assets = `${__dirname}/../../server/file/assets/`;
|
|
|
|
|
2018-05-03 11:03:14 +00:00
|
|
|
const commonReadableHandlerGenerator = (ctx: Koa.Context) => (e: Error): void => {
|
|
|
|
console.error(e);
|
|
|
|
ctx.status = 500;
|
|
|
|
};
|
2018-04-12 21:06:18 +00:00
|
|
|
|
|
|
|
export default async function(ctx: Koa.Context) {
|
|
|
|
// 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;
|
2018-05-04 09:02:09 +00:00
|
|
|
await send(ctx, '/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;
|
2018-05-04 07:48:18 +00:00
|
|
|
if (file.metadata.isExpired) {
|
2018-05-04 09:02:09 +00:00
|
|
|
await send(ctx, '/cache-expired.png', { root: assets });
|
2018-05-04 07:48:18 +00:00
|
|
|
} else {
|
2018-05-04 09:02:09 +00:00
|
|
|
await send(ctx, '/tombstone.png', { root: assets });
|
2018-05-04 07:48:18 +00:00
|
|
|
}
|
2018-04-17 11:04:19 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-05-03 11:12:08 +00:00
|
|
|
const sendRaw = async () => {
|
|
|
|
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-05-03 11:12:08 +00:00
|
|
|
// 画像以外
|
|
|
|
if (!file.contentType.startsWith('image/')) {
|
2018-05-03 11:03:14 +00:00
|
|
|
const readable = fs.createReadStream(`${__dirname}/assets/thumbnail-not-available.png`);
|
|
|
|
ctx.set('Content-Type', 'image/png');
|
|
|
|
ctx.body = readable;
|
2018-05-03 11:12:08 +00:00
|
|
|
} else if (file.contentType == 'image/gif') {
|
|
|
|
// GIF
|
|
|
|
await sendRaw();
|
2018-05-03 11:03:14 +00:00
|
|
|
} else {
|
|
|
|
const thumb = await DriveFileThumbnail.findOne({ 'metadata.originalId': fileId });
|
|
|
|
if (thumb != null) {
|
|
|
|
ctx.set('Content-Type', 'image/jpeg');
|
|
|
|
const bucket = await getDriveFileThumbnailBucket();
|
|
|
|
ctx.body = bucket.openDownloadStream(thumb._id);
|
|
|
|
} else {
|
2018-05-03 11:12:08 +00:00
|
|
|
await sendRaw();
|
2018-05-03 11:03:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ('download' in ctx.query) {
|
|
|
|
ctx.set('Content-Disposition', 'attachment');
|
|
|
|
}
|
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
|
|
|
}
|