feat: add content-length headers
This commit is contained in:
parent
786e6d5799
commit
2f0af385c7
6 changed files with 55 additions and 5 deletions
|
@ -5,6 +5,7 @@ export abstract class Datasource {
|
|||
|
||||
public abstract save(file: string, data: Buffer): Promise<void>;
|
||||
public abstract delete(file: string): Promise<void>;
|
||||
public abstract size(file: string): Promise<number>;
|
||||
public abstract get(file: string): Readable | Promise<Readable>;
|
||||
public abstract size(): Promise<number>;
|
||||
public abstract fullSize(): Promise<number>;
|
||||
}
|
|
@ -29,7 +29,13 @@ export class Local extends Datasource {
|
|||
}
|
||||
}
|
||||
|
||||
public async size(): Promise<number> {
|
||||
public async size(file: string): Promise<number> {
|
||||
const stats = await stat(join(process.cwd(), this.path, file));
|
||||
|
||||
return stats.size;
|
||||
}
|
||||
|
||||
public async fullSize(): Promise<number> {
|
||||
const files = await readdir(this.path);
|
||||
|
||||
let size = 0;
|
||||
|
|
|
@ -37,7 +37,16 @@ export class S3 extends Datasource {
|
|||
});
|
||||
}
|
||||
|
||||
public async size(): Promise<number> {
|
||||
public size(file: string): Promise<number> {
|
||||
return new Promise((res, rej) => {
|
||||
this.s3.statObject(this.config.bucket, file, (err, stat) => {
|
||||
if (err) rej(err);
|
||||
else res(stat.size);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async fullSize(): Promise<number> {
|
||||
return new Promise((res, rej) => {
|
||||
const objects = this.s3.listObjectsV2(this.config.bucket, '', true);
|
||||
let size = 0;
|
||||
|
|
|
@ -139,6 +139,7 @@ class SwiftContainer {
|
|||
body: data,
|
||||
});
|
||||
}
|
||||
|
||||
public async deleteObject(name: string): Promise<any> {
|
||||
const auth = await this.authenticate();
|
||||
|
||||
|
@ -147,8 +148,10 @@ class SwiftContainer {
|
|||
headers: this.generateHeaders(auth.token),
|
||||
});
|
||||
}
|
||||
|
||||
public async getObject(name: string): Promise<Readable> {
|
||||
const auth = await this.authenticate();
|
||||
|
||||
const arrayBuffer = await fetch(`${auth.swiftURL}/${this.options.credentials.container}/${name}`, {
|
||||
method: 'GET',
|
||||
headers: this.generateHeaders(auth.token, { Accept: '*/*' }),
|
||||
|
@ -156,6 +159,15 @@ class SwiftContainer {
|
|||
|
||||
return Readable.from(Buffer.from(arrayBuffer));
|
||||
}
|
||||
|
||||
public async headObject(name: string): Promise<any> {
|
||||
const auth = await this.authenticate();
|
||||
|
||||
return fetch(`${auth.swiftURL}/${this.options.credentials.container}/${name}`, {
|
||||
method: 'HEAD',
|
||||
headers: this.generateHeaders(auth.token),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class Swift extends Datasource {
|
||||
|
@ -164,6 +176,7 @@ export class Swift extends Datasource {
|
|||
|
||||
public constructor(public config: ConfigSwiftDatasource) {
|
||||
super();
|
||||
console.log(config);
|
||||
this.container = new SwiftContainer({
|
||||
auth_endpoint_url: config.auth_endpoint,
|
||||
credentials: {
|
||||
|
@ -201,7 +214,17 @@ export class Swift extends Datasource {
|
|||
}
|
||||
}
|
||||
|
||||
public async size(): Promise<number> {
|
||||
public async size(file: string): Promise<number> {
|
||||
try {
|
||||
const head = await this.container.headObject(file);
|
||||
|
||||
return head.headers.get('content-length') || 0;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public async fullSize(): Promise<number> {
|
||||
return this.container
|
||||
.listObjects()
|
||||
.then((objects) => objects.reduce((acc, object) => acc + object.bytes, 0))
|
||||
|
|
|
@ -22,6 +22,7 @@ start();
|
|||
|
||||
async function start() {
|
||||
const c = await import('../lib/config.js');
|
||||
// @ts-ignore
|
||||
config = c.default.default;
|
||||
|
||||
const d = await import('../lib/datasource.js');
|
||||
|
@ -134,7 +135,10 @@ async function rawFile(
|
|||
const data = await datasource.get(id);
|
||||
if (!data) return nextServer.render404(req, res as ServerResponse);
|
||||
const mimetype = mimes[extname(id)] ?? 'application/octet-stream';
|
||||
const size = await datasource.size(id);
|
||||
|
||||
res.setHeader('Content-Type', mimetype);
|
||||
res.setHeader('Content-Length', size);
|
||||
|
||||
data.pipe(res);
|
||||
data.on('error', () => nextServer.render404(req, res as ServerResponse));
|
||||
|
@ -151,7 +155,11 @@ async function rawFileDb(
|
|||
const data = await datasource.get(image.file);
|
||||
if (!data) return nextServer.render404(req, res as ServerResponse);
|
||||
|
||||
const size = await datasource.size(image.file);
|
||||
|
||||
res.setHeader('Content-Type', image.mimetype);
|
||||
res.setHeader('Content-Length', size);
|
||||
|
||||
data.pipe(res);
|
||||
data.on('error', () => nextServer.render404(req, res as ServerResponse));
|
||||
data.on('end', () => res.end());
|
||||
|
@ -176,7 +184,10 @@ async function fileDb(
|
|||
const data = await datasource.get(image.file);
|
||||
if (!data) return this.nextServer.render404(req, res as ServerResponse);
|
||||
|
||||
const size = await datasource.size(image.file);
|
||||
|
||||
res.setHeader('Content-Type', image.mimetype);
|
||||
res.setHeader('Content-Length', size);
|
||||
data.pipe(res);
|
||||
data.on('error', () => nextServer.render404(req, res as ServerResponse));
|
||||
data.on('end', () => res.end());
|
||||
|
|
|
@ -44,7 +44,7 @@ export function bytesToRead(bytes: number) {
|
|||
|
||||
|
||||
export async function getStats(prisma: PrismaClient, datasource: Datasource) {
|
||||
const size = await datasource.size();
|
||||
const size = await datasource.fullSize();
|
||||
const byUser = await prisma.image.groupBy({
|
||||
by: ['userId'],
|
||||
_count: {
|
||||
|
|
Loading…
Reference in a new issue