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" };
|
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 { useCallback, useMemo, useState, useTransition } from "react";
|
||||||
import { ContentCard } from "@/components/public/ui";
|
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";
|
import { HABBO_FONT_GROUPS, buildFontUrl } from "@/components/public/habbo-fonts";
|
||||||
|
|
||||||
export default function LogoGenerator() {
|
export default function LogoGenerator() {
|
||||||
@@ -39,25 +39,17 @@ export default function LogoGenerator() {
|
|||||||
window.open(gifUrl, "_blank");
|
window.open(gifUrl, "_blank");
|
||||||
}, [gifUrl]);
|
}, [gifUrl]);
|
||||||
|
|
||||||
const handleSave = useCallback(async () => {
|
const handleSave = useCallback(() => {
|
||||||
setSaveStatus("saving");
|
setSaveStatus("saving");
|
||||||
try {
|
startTransition(async () => {
|
||||||
const res = await fetch(gifUrl);
|
const result = await saveLogoFromUrl(gifUrl);
|
||||||
const blob = await res.blob();
|
setSaveStatus(result.success ? "done" : "error");
|
||||||
const ext = blob.type === "image/gif" ? "gif" : "png";
|
if (result.success) {
|
||||||
const file = new File([blob], `logo.${ext}`, { type: blob.type });
|
setTimeout(() => setSaveStatus("idle"), 3000);
|
||||||
const fd = new FormData();
|
} else {
|
||||||
fd.append("file", file);
|
setTimeout(() => setSaveStatus("idle"), 3000);
|
||||||
|
}
|
||||||
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);
|
|
||||||
}
|
|
||||||
}, [gifUrl, startTransition]);
|
}, [gifUrl, startTransition]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in new issue
Block a user