feat: configurable upload size limit (default 10MB)
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user