mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-22 23:43:09 +02:00
upd: introduce a separate ./cache dir and cache video thumbnails there
This commit is contained in:
parent
bc24e6a294
commit
a3c302e756
4 changed files with 41 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -54,6 +54,7 @@ api-docs.json
|
||||||
*.code-workspace
|
*.code-workspace
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/files
|
/files
|
||||||
|
/cache
|
||||||
ormconfig.json
|
ormconfig.json
|
||||||
temp
|
temp
|
||||||
/packages/frontend/src/**/*.stories.ts
|
/packages/frontend/src/**/*.stories.ts
|
||||||
|
|
|
@ -20,6 +20,7 @@ services:
|
||||||
- shonk
|
- shonk
|
||||||
volumes:
|
volumes:
|
||||||
- ./files:/sharkey/files
|
- ./files:/sharkey/files
|
||||||
|
- ./cache:/sharkey/cache
|
||||||
- ./.config:/sharkey/.config:ro
|
- ./.config:/sharkey/.config:ro
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
|
|
|
@ -16,6 +16,7 @@ const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
|
|
||||||
const path = Path.resolve(_dirname, '../../../../files');
|
const path = Path.resolve(_dirname, '../../../../files');
|
||||||
|
const cachePath = Path.resolve(_dirname, '../../../../cache');
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class InternalStorageService {
|
export class InternalStorageService {
|
||||||
|
@ -30,11 +31,26 @@ export class InternalStorageService {
|
||||||
return Path.resolve(path, key);
|
return Path.resolve(path, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public resolveCachePath(key: string) {
|
||||||
|
return Path.resolve(cachePath, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public existsCache(key: string) {
|
||||||
|
return fs.existsSync(this.resolveCachePath(key));
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public read(key: string) {
|
public read(key: string) {
|
||||||
return fs.createReadStream(this.resolvePath(key));
|
return fs.createReadStream(this.resolvePath(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public readCache(key: string) {
|
||||||
|
return fs.createReadStream(this.resolveCachePath(key));
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public saveFromPath(key: string, srcPath: string) {
|
public saveFromPath(key: string, srcPath: string) {
|
||||||
fs.mkdirSync(path, { recursive: true });
|
fs.mkdirSync(path, { recursive: true });
|
||||||
|
@ -49,8 +65,19 @@ export class InternalStorageService {
|
||||||
return `${this.config.url}/files/${key}`;
|
return `${this.config.url}/files/${key}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public saveCacheFromBuffer(key: string, data: Buffer) {
|
||||||
|
fs.mkdirSync(cachePath, { recursive: true });
|
||||||
|
fs.writeFileSync(this.resolveCachePath(key), data);
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public del(key: string) {
|
public del(key: string) {
|
||||||
fs.unlink(this.resolvePath(key), () => {});
|
fs.unlink(this.resolvePath(key), () => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public delCache(key: string) {
|
||||||
|
fs.unlink(this.resolveCachePath(key), () => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import * as fs from 'node:fs';
|
import * as fs from 'node:fs';
|
||||||
|
import * as crypto from 'node:crypto';
|
||||||
import { fileURLToPath } from 'node:url';
|
import { fileURLToPath } from 'node:url';
|
||||||
import { dirname } from 'node:path';
|
import { dirname } from 'node:path';
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
@ -33,6 +34,7 @@ const _filename = fileURLToPath(import.meta.url);
|
||||||
const _dirname = dirname(_filename);
|
const _dirname = dirname(_filename);
|
||||||
|
|
||||||
const assets = `${_dirname}/../../server/file/assets/`;
|
const assets = `${_dirname}/../../server/file/assets/`;
|
||||||
|
const cacheDir = `${_dirname}/../../../../cache/`;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FileServerService {
|
export class FileServerService {
|
||||||
|
@ -380,6 +382,14 @@ export class FileServerService {
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
private async videoThumbnailHandler(request: FastifyRequest<{ Querystring: { url: string; }; }>, reply: FastifyReply) {
|
private async videoThumbnailHandler(request: FastifyRequest<{ Querystring: { url: string; }; }>, reply: FastifyReply) {
|
||||||
|
const cacheKey = crypto.createHash('md5').update(request.query.url).digest('base64url');
|
||||||
|
const cacheFile = `videoThumbnail-${cacheKey}.webp`;
|
||||||
|
if (this.internalStorageService.existsCache(cacheFile)) {
|
||||||
|
reply.header('Content-Type', 'image/webp');
|
||||||
|
reply.header('Cache-Control', 'max-age=31536000, immutable');
|
||||||
|
return reply.sendFile(cacheFile, cacheDir);
|
||||||
|
}
|
||||||
|
|
||||||
const file = await this.getStreamAndTypeFromUrl(request.query.url);
|
const file = await this.getStreamAndTypeFromUrl(request.query.url);
|
||||||
|
|
||||||
if (file === '404') {
|
if (file === '404') {
|
||||||
|
@ -414,6 +424,8 @@ export class FileServerService {
|
||||||
file.cleanup();
|
file.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.internalStorageService.saveCacheFromBuffer(cacheFile, image.data);
|
||||||
|
|
||||||
reply.header('Content-Type', image.type);
|
reply.header('Content-Type', image.type);
|
||||||
reply.header('Cache-Control', 'max-age=31536000, immutable');
|
reply.header('Cache-Control', 'max-age=31536000, immutable');
|
||||||
return image.data;
|
return image.data;
|
||||||
|
|
Loading…
Reference in a new issue