feat: configurable upload size limit (default 10MB)

This commit is contained in:
Xianren Studio
2026-08-13 23:55:25 +08:00
parent ad0efe249c
commit bd3f648ccd
3 changed files with 20 additions and 8 deletions
+1
View File
@@ -65,6 +65,7 @@ impl CoreApp {
("api_port", "1234".to_string()), ("api_port", "1234".to_string()),
("api_key", String::new()), ("api_key", String::new()),
("api_enabled", "false".to_string()), ("api_enabled", "false".to_string()),
("upload_max_mb", "10".to_string()),
]; ];
for (key, value) in defaults { for (key, value) in defaults {
let _ = settings::set(&db, key, &value); let _ = settings::set(&db, key, &value);
+14 -8
View File
@@ -50,9 +50,6 @@ const TEXT_EXTENSIONS = new Set([
"yml", "toml", "ini", "sh", "ps1", "bat", "sql", "env", "gitignore", "yml", "toml", "ini", "sh", "ps1", "bat", "sql", "env", "gitignore",
]); ]);
const MAX_IMAGE_SIZE = 3 * 1024 * 1024;
const MAX_TEXT_SIZE = 100 * 1024;
export default function ChatPage() { export default function ChatPage() {
const models = useStore((s) => s.models); const models = useStore((s) => s.models);
const conversations = useStore((s) => s.conversations); const conversations = useStore((s) => s.conversations);
@@ -75,6 +72,7 @@ export default function ChatPage() {
const [editingDraft, setEditingDraft] = useState(""); const [editingDraft, setEditingDraft] = useState("");
const [versionsFor, setVersionsFor] = useState<Record<string, MessageVersion[]>>({}); const [versionsFor, setVersionsFor] = useState<Record<string, MessageVersion[]>>({});
const [attachments, setAttachments] = useState<Attachment[]>([]); const [attachments, setAttachments] = useState<Attachment[]>([]);
const [uploadLimitMb, setUploadLimitMb] = useState(10);
const bottomRef = useRef<HTMLDivElement>(null); const bottomRef = useRef<HTMLDivElement>(null);
const fileInputRef = useRef<HTMLInputElement>(null); const fileInputRef = useRef<HTMLInputElement>(null);
@@ -104,6 +102,13 @@ export default function ChatPage() {
} }
}, [models, selectedModelId]); }, [models, selectedModelId]);
useEffect(() => {
api.settingsGet().then((s) => {
const v = Number(s.upload_max_mb);
if (v > 0) setUploadLimitMb(v);
});
}, []);
useEffect(() => { useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: "smooth" }); bottomRef.current?.scrollIntoView({ behavior: "smooth" });
}, [messages]); }, [messages]);
@@ -302,11 +307,12 @@ export default function ChatPage() {
} }
async function handleFiles(files: FileList | File[]) { async function handleFiles(files: FileList | File[]) {
const maxBytes = uploadLimitMb * 1024 * 1024;
for (const file of Array.from(files)) { for (const file of Array.from(files)) {
const ext = file.name.split(".").pop()?.toLowerCase() ?? ""; const ext = file.name.split(".").pop()?.toLowerCase() ?? "";
if (file.type.startsWith("image/") || ["png", "jpg", "jpeg", "webp", "gif", "bmp"].includes(ext)) { if (file.type.startsWith("image/") || ["png", "jpg", "jpeg", "webp", "gif", "bmp"].includes(ext)) {
if (file.size > MAX_IMAGE_SIZE) { if (file.size > maxBytes) {
setError(`图片 ${file.name} 超过 3MB,已跳过`); setError(`图片 ${file.name} 超过上限 ${uploadLimitMb}MB,已跳过`);
continue; continue;
} }
const dataUrl = await readAsDataUrl(file); const dataUrl = await readAsDataUrl(file);
@@ -315,8 +321,8 @@ export default function ChatPage() {
{ id: crypto.randomUUID(), kind: "image", name: file.name, size: file.size, dataUrl }, { id: crypto.randomUUID(), kind: "image", name: file.name, size: file.size, dataUrl },
]); ]);
} else if (file.type.startsWith("text/") || TEXT_EXTENSIONS.has(ext)) { } else if (file.type.startsWith("text/") || TEXT_EXTENSIONS.has(ext)) {
if (file.size > MAX_TEXT_SIZE) { if (file.size > maxBytes) {
setError(`文件 ${file.name} 超过 100KB,已跳过`); setError(`文件 ${file.name} 超过上限 ${uploadLimitMb}MB,已跳过`);
continue; continue;
} }
const text = await file.text(); const text = await file.text();
@@ -468,7 +474,7 @@ export default function ChatPage() {
<button <button
className="mb-1 flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border bg-panel-2 text-slate-400 hover:bg-panel-2/60 hover:text-slate-200" className="mb-1 flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border border-border bg-panel-2 text-slate-400 hover:bg-panel-2/60 hover:text-slate-200"
onClick={() => fileInputRef.current?.click()} onClick={() => fileInputRef.current?.click()}
title="上传图片或文本文件" title={`上传图片或文本文件(上限 ${uploadLimitMb}MB`}
> >
<Icon name="paperclip" className="h-4 w-4" /> <Icon name="paperclip" className="h-4 w-4" />
</button> </button>
+5
View File
@@ -77,6 +77,11 @@ export default function SettingsPage() {
value={settings.backend ?? ""} value={settings.backend ?? ""}
onSave={(v) => handleSave("backend", v)} onSave={(v) => handleSave("backend", v)}
/> />
<SettingInput
label="上传图片/文件大小上限(MB"
value={settings.upload_max_mb ?? "10"}
onSave={(v) => handleSave("upload_max_mb", v)}
/>
</div> </div>
</div> </div>