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:
@@ -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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user