fix: use server-side fetch for logo save (bypass CORS), detect file MIME on extension
This commit is contained in:
1 parent
6df4fe2ddd
commit
917437c5ef
2 files changed
+44
-19
No files matched your search
@@ -38,3 +38,36 @@ export async function saveLogo(formData: FormData): Promise<{ success: boolean;
|
||||
return { success: false, error: e instanceof Error ? e.message : "Unknown error" };
|
||||
}
|
||||
}
|
||||
|
||||
export async function saveLogoFromUrl(gifUrl: string): Promise<{ success: boolean; url?: string; error?: string }> {
|
||||
try {
|
||||
const res = await fetch(gifUrl);
|
||||
if (!res.ok) return { success: false, error: `Failed to fetch GIF: ${res.status}` };
|
||||
|
||||
const contentType = res.headers.get("content-type") ?? "image/gif";
|
||||
const buffer = Buffer.from(await res.arrayBuffer());
|
||||
|
||||
const mimeExt: Record<string, string> = { "image/png": "png", "image/gif": "gif", "image/jpeg": "jpg", "image/webp": "webp" };
|
||||
const ext = mimeExt[contentType] ?? "gif";
|
||||
const filename = `logo-${Date.now()}-${Math.random().toString(36).slice(2, 8)}.${ext}`;
|
||||
const dir = path.join(process.cwd(), MEDIA_DIR);
|
||||
const filePath = path.join(dir, filename);
|
||||
|
||||
await writeFile(filePath, buffer);
|
||||
|
||||
const url = `/api/media/${filename}`;
|
||||
|
||||
await prisma.websiteSetting.upsert({
|
||||
where: { key: "cms_logo" },
|
||||
update: { value: url },
|
||||
create: { key: "cms_logo", value: url, comment: "Logo (generator)" },
|
||||
});
|
||||
|
||||
siteSettings.reload();
|
||||
revalidatePath("/", "layout");
|
||||
|
||||
return { success: true, url };
|
||||
} catch (e) {
|
||||
return { success: false, error: e instanceof Error ? e.message : "Unknown error" };
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useCallback, useMemo, useState, useTransition } from "react";
|
||||
import { ContentCard } from "@/components/public/ui";
|
||||
import { saveLogo } from "@/actions/save-logo";
|
||||
import { saveLogoFromUrl } from "@/actions/save-logo";
|
||||
import { HABBO_FONT_GROUPS, buildFontUrl } from "@/components/public/habbo-fonts";
|
||||
|
||||
export default function LogoGenerator() {
|
||||
@@ -39,25 +39,17 @@ export default function LogoGenerator() {
|
||||
window.open(gifUrl, "_blank");
|
||||
}, [gifUrl]);
|
||||
|
||||
const handleSave = useCallback(async () => {
|
||||
const handleSave = useCallback(() => {
|
||||
setSaveStatus("saving");
|
||||
try {
|
||||
const res = await fetch(gifUrl);
|
||||
const blob = await res.blob();
|
||||
const ext = blob.type === "image/gif" ? "gif" : "png";
|
||||
const file = new File([blob], `logo.${ext}`, { type: blob.type });
|
||||
const fd = new FormData();
|
||||
fd.append("file", file);
|
||||
|
||||
startTransition(async () => {
|
||||
const result = await saveLogo(fd);
|
||||
setSaveStatus(result.success ? "done" : "error");
|
||||
if (result.success) setTimeout(() => setSaveStatus("idle"), 3000);
|
||||
});
|
||||
} catch {
|
||||
setSaveStatus("error");
|
||||
setTimeout(() => setSaveStatus("idle"), 3000);
|
||||
}
|
||||
startTransition(async () => {
|
||||
const result = await saveLogoFromUrl(gifUrl);
|
||||
setSaveStatus(result.success ? "done" : "error");
|
||||
if (result.success) {
|
||||
setTimeout(() => setSaveStatus("idle"), 3000);
|
||||
} else {
|
||||
setTimeout(() => setSaveStatus("idle"), 3000);
|
||||
}
|
||||
});
|
||||
}, [gifUrl, startTransition]);
|
||||
|
||||
return (
|
||||
|
||||
Reference in new issue
Block a user