fix: 图片上传增加压缩(1024px/JPEG 0.7),对齐 AgnesAIDesktop 方案

问题: 上传图片后 AI 无法识别,回复没有图像分析工具
根因: 原图 base64 直接发送(5-10MB),Agnes AI 可能因体积过大拒绝处理

对比 AgnesAIDesktop(可正常工作):
- 上传后用 canvas 压缩: max 1024px, JPEG quality 0.7
- 小图(<500KB且尺寸未超标)保留原图

修复:
- ChatInput 新增 compressImage 函数(来自 AgnesAIDesktop 验证方案)
- processFile 中图片读取后立即压缩再存 preview
This commit is contained in:
thzxx
2026-06-27 22:27:56 +08:00
parent baeff6e958
commit 4924e2d339
+39 -2
View File
@@ -69,12 +69,13 @@ export function ChatInput(): React.JSX.Element {
const attachment: Attachment = { id: `att_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`, file, type }; const attachment: Attachment = { id: `att_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`, file, type };
if (type === 'image') { if (type === 'image') {
// 图片转 base64 data URL // 图片转 base64 data URL → 压缩(限制 1024px, JPEG 0.7
attachment.preview = await new Promise<string>((resolve) => { const dataUri = await new Promise<string>((resolve) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onload = () => resolve(reader.result as string); reader.onload = () => resolve(reader.result as string);
reader.readAsDataURL(file); reader.readAsDataURL(file);
}); });
attachment.preview = await compressImage(dataUri, 1024, 0.7);
} else if (type === 'text') { } else if (type === 'text') {
// 文本文件读取内容 // 文本文件读取内容
attachment.textContent = await new Promise<string>((resolve) => { attachment.textContent = await new Promise<string>((resolve) => {
@@ -309,3 +310,39 @@ function AttachmentPreview({ attachment, onRemove }: { attachment: Attachment; o
</Box> </Box>
); );
} }
/**
* 压缩图片:限制最大边长,输出 JPEG base64。
* 小图(< 500KB 且尺寸未超标)直接返回原图,避免重复编码。
*
* @see AgnesAIDesktop — 已验证 Agnes AI 可正常处理压缩后的图片
*/
function compressImage(
dataUri: string,
maxSize: number,
quality: number,
): Promise<string> {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
let { width, height } = img;
if (width <= maxSize && height <= maxSize && dataUri.length < 500 * 1024) {
resolve(dataUri);
return;
}
if (width > height) {
if (width > maxSize) { height = Math.round((height * maxSize) / width); width = maxSize; }
} else {
if (height > maxSize) { width = Math.round((width * maxSize) / height); height = maxSize; }
}
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d')!;
ctx.drawImage(img, 0, 0, width, height);
resolve(canvas.toDataURL('image/jpeg', quality));
};
img.onerror = () => reject(new Error('图片加载失败'));
img.src = dataUri;
});
}