High res uploads
Deploy / deploy (push) Successful in 3m16s

This commit is contained in:
twotalesanimation
2026-06-25 09:56:41 +02:00
parent d2e686335f
commit b683976cc6
9 changed files with 364 additions and 2 deletions
+68
View File
@@ -219,3 +219,71 @@ function getPublicUrl(key: string, provider: StorageProvider): string {
// Fallback
return `/${key}`;
}
// ── Hetzner Object Storage (dedicated high-res bucket) ───────────────────────
function buildHetznerClient(): S3Client {
return new S3Client({
region: "auto",
endpoint: process.env.HETZNER_ENDPOINT!,
credentials: {
accessKeyId: process.env.HETZNER_ACCESS_KEY!,
secretAccessKey: process.env.HETZNER_SECRET_KEY!,
},
});
}
function getHetznerBucket(): string {
return process.env.HETZNER_BUCKET_NAME ?? "vfx-review";
}
/**
* Upload a buffer directly to the Hetzner bucket (always uses Hetzner credentials,
* regardless of the global STORAGE_PROVIDER setting).
*/
export async function uploadToHetzner(
buffer: Buffer,
fileName: string,
contentType: string,
folder: string = "highres"
): Promise<{ key: string }> {
const key = `${folder}/${randomUUID()}-${fileName}`;
const client = buildHetznerClient();
await client.send(
new PutObjectCommand({
Bucket: getHetznerBucket(),
Key: key,
Body: buffer,
ContentType: contentType,
})
);
return { key };
}
/**
* Generate a presigned download URL from Hetzner that forces a file download
* with the original filename preserved via Content-Disposition.
*/
export async function generateHetznerDownloadUrl(
key: string,
originalFilename: string,
expiresIn: number = 3600
): Promise<string> {
const client = buildHetznerClient();
const command = new GetObjectCommand({
Bucket: getHetznerBucket(),
Key: key,
ResponseContentDisposition: `attachment; filename="${originalFilename}"`,
});
return getSignedUrl(client, command, { expiresIn });
}
/**
* Delete a file from the Hetzner bucket by key.
*/
export async function deleteFromHetzner(key: string): Promise<void> {
const client = buildHetznerClient();
await client.send(
new DeleteObjectCommand({ Bucket: getHetznerBucket(), Key: key })
);
}