perf: binary avatar

This commit is contained in:
archer
2023-06-14 22:26:11 +08:00
parent 7c159d8aba
commit 7c52cec0ea
16 changed files with 98 additions and 14 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -5,3 +5,5 @@ import type { InitDateResponse } from '@/pages/api/system/getInitData';
export const getInitData = () => GET<InitDateResponse>('/system/getInitData');
export const getSystemModelList = () => GET<ChatModelItemType[]>('/system/getModels');
export const uploadImg = (base64Img: string) => POST<string>('/system/uploadImage', { base64Img });

View File

@@ -1,4 +1,4 @@
import React, { memo, useMemo, useEffect } from 'react';
import React, { memo, useMemo } from 'react';
import ReactMarkdown from 'react-markdown';
import { formatLinkText } from '@/utils/tools';
import remarkGfm from 'remark-gfm';

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,25 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Image } from '@/service/mongo';
// get the models available to the system
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { id } = req.query;
const data = await Image.findById(id);
if (!data) {
throw new Error('no image');
}
res.setHeader('Content-Type', 'image/jpeg');
res.send(data.binary);
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}

View File

@@ -0,0 +1,26 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@/service/response';
import { connectToDatabase, Image } from '@/service/mongo';
import { authUser } from '@/service/utils/auth';
// get the models available to the system
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { userId } = await authUser({ req, authToken: true });
const { base64Img } = req.body;
const base64Data = base64Img.split(',')[1];
const { _id } = await Image.create({
userId,
binary: Buffer.from(base64Data, 'base64')
});
jsonRes(res, { data: `/api/system/img/${_id}` });
} catch (error) {
jsonRes(res, {
code: 500,
error
});
}
}

View File

@@ -163,7 +163,7 @@ const Home = () => {
position={'absolute'}
userSelect={'none'}
>
<Image src="/icon/logo.png" w={['70px', '120px']} h={['70px', '120px']} alt={''}></Image>
<Image src="/icon/logo2.png" w={['70px', '120px']} h={['70px', '120px']} alt={''}></Image>
<Box
className={styles.textlg}
fontWeight={'bold'}

View File

@@ -114,12 +114,14 @@ const Info = (
const file = e[0];
if (!file) return;
try {
const base64 = await compressImg({
const src = await compressImg({
file,
maxW: 100,
maxH: 100
});
setValue('avatar', base64);
setValue('avatar', src);
setRefresh((state) => !state);
} catch (err: any) {
toast({

View File

@@ -104,12 +104,12 @@ const ModelEditForm = ({
const file = e[0];
if (!file) return;
try {
const base64 = await compressImg({
const src = await compressImg({
file,
maxW: 100,
maxH: 100
});
setValue('avatar', base64);
setValue('avatar', src);
setRefresh((state) => !state);
} catch (err: any) {
toast({

View File

@@ -14,6 +14,7 @@ import dynamic from 'next/dynamic';
import { useSelectFile } from '@/hooks/useSelectFile';
import { compressImg } from '@/utils/file';
import { useCopyData } from '@/utils/tools';
import Loading from '@/components/Loading';
import Avatar from '@/components/Avatar';
import MyIcon from '@/components/Icon';
@@ -112,14 +113,15 @@ const NumberSetting = ({ tableType }: { tableType: `${TableEnum}` }) => {
const file = e[0];
if (!file) return;
try {
const base64 = await compressImg({
const src = await compressImg({
file,
maxW: 100,
maxH: 100
});
onclickSave({
...userInfo,
avatar: base64
avatar: src
});
} catch (err: any) {
toast({

View File

@@ -0,0 +1,15 @@
import { Schema, model, models, Model } from 'mongoose';
const ImageSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: 'user',
required: true
},
binary: {
type: Buffer
}
});
export const Image: Model<{ userId: string; binary: Buffer }> =
models['image'] || model('image', ImageSchema);

View File

@@ -68,3 +68,4 @@ export * from './models/shareChat';
export * from './models/kb';
export * from './models/inform';
export * from './models/system';
export * from './models/image';

View File

@@ -3,6 +3,7 @@ import Papa from 'papaparse';
import { getOpenAiEncMap } from './plugin/openai';
import { getErrText } from './tools';
import { OpenAiChatEnum } from '@/constants/model';
import { uploadImg } from '@/api/system';
/**
* 读取 txt 文件内容
@@ -218,11 +219,11 @@ export const compressImg = ({
new Promise<string>((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
reader.onload = async () => {
const img = new Image();
// @ts-ignore
img.src = reader.result;
img.onload = () => {
img.onload = async () => {
let width = img.width;
let height = img.height;
@@ -248,14 +249,24 @@ export const compressImg = ({
}
ctx.drawImage(img, 0, 0, width, height);
const compressedDataUrl = canvas.toDataURL(file.type, 1);
const compressedDataUrl = canvas.toDataURL(file.type, 0.8);
// 移除 canvas 元素
canvas.remove();
if (compressedDataUrl.length > maxSize) {
return reject('图片太大了');
}
resolve(compressedDataUrl);
const src = await (async () => {
try {
const src = await uploadImg(compressedDataUrl);
return src;
} catch (error) {
return compressedDataUrl;
}
})();
resolve(src);
};
};
reader.onerror = (err) => {