feat(extra) : detect uploaded image ratio
CI / Verify (push) Successful in 1m5s
CI / Build immutable images and deploy (push) Successful in 3m8s

This commit is contained in:
2026-09-04 21:23:26 +07:00 Unverified
parent c0d0e0c18f
commit 513e37ad83
11 changed files with 3475 additions and 59 deletions
+17 -2
View File
@@ -1,6 +1,7 @@
import "server-only";
import { and, eq, sql } from "drizzle-orm";
import sharp from "sharp";
import { getDb } from "@/db";
import { media } from "@/db/schema";
@@ -41,7 +42,7 @@ export async function createPendingMedia(
export async function uploadPublicMedia(
file: File,
authorId: string,
): Promise<{ id: string; url: string; fileName: string }> {
): Promise<{ id: string; url: string; fileName: string; width: number; height: number }> {
const parsed = mediaUploadSchema.parse({
fileName: file.name,
mimeType: file.type,
@@ -51,6 +52,12 @@ export async function uploadPublicMedia(
if (!hasValidImageSignature(bytes.subarray(0, 16), parsed.mimeType)) {
throw new Error("ไฟล์ไม่ตรงกับชนิดรูปภาพที่ระบุ");
}
const metadata = await sharp(bytes).metadata();
const width = metadata.autoOrient.width || metadata.width;
const height = metadata.autoOrient.height || metadata.height;
if (!width || !height) {
throw new Error("ไม่สามารถอ่านขนาดรูปภาพได้");
}
const id = crypto.randomUUID();
const objectKey = `uploads/${id}/${safeObjectFileName(parsed.fileName)}`;
@@ -63,6 +70,8 @@ export async function uploadPublicMedia(
fileName: parsed.fileName,
mimeType: parsed.mimeType,
byteSize: parsed.byteSize,
width,
height,
status: "ready",
currentReferenceCount: 0,
createdById: authorId,
@@ -71,7 +80,13 @@ export async function uploadPublicMedia(
await storage.delete(objectKey).catch(() => undefined);
throw cause;
}
return { id, url: publicMediaUrl(objectKey), fileName: parsed.fileName };
return {
id,
url: publicMediaUrl(objectKey),
fileName: parsed.fileName,
width,
height,
};
}
export async function addCurrentMediaReference(mediaId: string): Promise<void> {