mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-02 16:20:36 -05:00
Move app to apps/web-react in pnpm workspace layout
This commit is contained in:
53
apps/web-react/app/features/img-upload/image-bytes.server.ts
Normal file
53
apps/web-react/app/features/img-upload/image-bytes.server.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import invariant from "~/utils/invariant";
|
||||
|
||||
export type ImageExtension = "webp" | "png" | "jpeg";
|
||||
|
||||
/**
|
||||
* Decodes a base64 image data URL to a buffer, resolving the format from the buffer's own magic
|
||||
* bytes rather than trusting the client-declared mime type, and asserting it is one of
|
||||
* `allowedExtensions`.
|
||||
*/
|
||||
export function dataUrlToImageBuffer(
|
||||
dataUrl: string,
|
||||
allowedExtensions: ReadonlyArray<ImageExtension>,
|
||||
) {
|
||||
const base64 = dataUrl.slice(dataUrl.indexOf(",") + 1);
|
||||
const buffer = Buffer.from(base64, "base64");
|
||||
|
||||
const extension = imageExtensionFromMagicBytes(buffer);
|
||||
invariant(
|
||||
extension && allowedExtensions.includes(extension),
|
||||
`Submitted image is not a valid ${allowedExtensions.join(" or ")}`,
|
||||
);
|
||||
|
||||
return { buffer, extension };
|
||||
}
|
||||
|
||||
function imageExtensionFromMagicBytes(buffer: Buffer): ImageExtension | null {
|
||||
if (
|
||||
buffer.length > 12 &&
|
||||
buffer.toString("ascii", 0, 4) === "RIFF" &&
|
||||
buffer.toString("ascii", 8, 12) === "WEBP"
|
||||
) {
|
||||
return "webp";
|
||||
}
|
||||
|
||||
if (
|
||||
buffer.length > 8 &&
|
||||
buffer[0] === 0x89 &&
|
||||
buffer.toString("ascii", 1, 4) === "PNG"
|
||||
) {
|
||||
return "png";
|
||||
}
|
||||
|
||||
if (
|
||||
buffer.length > 3 &&
|
||||
buffer[0] === 0xff &&
|
||||
buffer[1] === 0xd8 &&
|
||||
buffer[2] === 0xff
|
||||
) {
|
||||
return "jpeg";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user