mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-27 00:17:31 +00:00
feat: file relate kb
This commit is contained in:
@@ -26,8 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
|
|
||||||
const encoding = jschardet.detect(buffer)?.encoding;
|
const encoding = jschardet.detect(buffer)?.encoding;
|
||||||
|
|
||||||
res.setHeader('encoding', encoding);
|
res.setHeader('Content-Type', `${file.contentType}; charset=${encoding}`);
|
||||||
res.setHeader('Content-Type', file.contentType);
|
|
||||||
res.setHeader('Cache-Control', 'public, max-age=3600');
|
res.setHeader('Cache-Control', 'public, max-age=3600');
|
||||||
res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(file.filename)}"`);
|
res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(file.filename)}"`);
|
||||||
|
|
||||||
|
@@ -38,7 +38,7 @@ class UploadModel {
|
|||||||
}).any();
|
}).any();
|
||||||
|
|
||||||
async doUpload(req: NextApiRequest, res: NextApiResponse) {
|
async doUpload(req: NextApiRequest, res: NextApiResponse) {
|
||||||
return new Promise<{ files: FileType[] }>((resolve, reject) => {
|
return new Promise<{ files: FileType[]; metadata: Record<string, any> }>((resolve, reject) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.uploader(req, res, (error) => {
|
this.uploader(req, res, (error) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
@@ -46,11 +46,22 @@ class UploadModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
// @ts-ignore
|
files:
|
||||||
files: req.files?.map((file) => ({
|
// @ts-ignore
|
||||||
...file,
|
req.files?.map((file) => ({
|
||||||
originalname: decodeURIComponent(file.originalname)
|
...file,
|
||||||
}))
|
originalname: decodeURIComponent(file.originalname)
|
||||||
|
})) || [],
|
||||||
|
metadata: (() => {
|
||||||
|
if (!req.body?.metadata) return {};
|
||||||
|
try {
|
||||||
|
return JSON.parse(req.body.metadata);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
})()
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -64,7 +75,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
const { userId } = await authUser({ req, authToken: true });
|
const { userId } = await authUser({ req, authToken: true });
|
||||||
|
|
||||||
const { files = [] } = await upload.doUpload(req, res);
|
const { files, metadata } = await upload.doUpload(req, res);
|
||||||
|
|
||||||
const gridFs = new GridFSStorage('dataset', userId);
|
const gridFs = new GridFSStorage('dataset', userId);
|
||||||
|
|
||||||
@@ -74,8 +85,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
path: file.path,
|
path: file.path,
|
||||||
filename: file.originalname,
|
filename: file.originalname,
|
||||||
metadata: {
|
metadata: {
|
||||||
|
...metadata,
|
||||||
contentType: file.mimetype,
|
contentType: file.mimetype,
|
||||||
encoding: file.encoding,
|
|
||||||
userId
|
userId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@@ -5,6 +5,7 @@ import { authUser } from '@/service/utils/auth';
|
|||||||
import { PgClient } from '@/service/pg';
|
import { PgClient } from '@/service/pg';
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import { PgTrainingTableName } from '@/constants/plugin';
|
import { PgTrainingTableName } from '@/constants/plugin';
|
||||||
|
import { GridFSStorage } from '@/service/lib/gridfs';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||||
try {
|
try {
|
||||||
@@ -21,24 +22,20 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
|||||||
|
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
|
|
||||||
// delete all pg data
|
|
||||||
await PgClient.delete(PgTrainingTableName, {
|
|
||||||
where: [['user_id', userId], 'AND', ['kb_id', id]]
|
|
||||||
});
|
|
||||||
|
|
||||||
// delete training data
|
// delete training data
|
||||||
await TrainingData.deleteMany({
|
await TrainingData.deleteMany({
|
||||||
userId,
|
userId,
|
||||||
kbId: id
|
kbId: id
|
||||||
});
|
});
|
||||||
|
|
||||||
// delete related app
|
// delete all pg data
|
||||||
await App.updateMany(
|
await PgClient.delete(PgTrainingTableName, {
|
||||||
{
|
where: [['user_id', userId], 'AND', ['kb_id', id]]
|
||||||
userId
|
});
|
||||||
},
|
|
||||||
{ $pull: { 'chat.relatedKbs': new Types.ObjectId(id) } }
|
// delete related files
|
||||||
);
|
const gridFs = new GridFSStorage('dataset', userId);
|
||||||
|
await gridFs.deleteFilesByKbId(id);
|
||||||
|
|
||||||
// delete kb data
|
// delete kb data
|
||||||
await KB.findOneAndDelete({
|
await KB.findOneAndDelete({
|
||||||
|
@@ -19,6 +19,7 @@ import dynamic from 'next/dynamic';
|
|||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import { FetchResultItem, DatasetItemType } from '@/types/plugin';
|
import { FetchResultItem, DatasetItemType } from '@/types/plugin';
|
||||||
import { getErrText } from '@/utils/tools';
|
import { getErrText } from '@/utils/tools';
|
||||||
|
import { useUserStore } from '@/store/user';
|
||||||
|
|
||||||
const UrlFetchModal = dynamic(() => import('./UrlFetchModal'));
|
const UrlFetchModal = dynamic(() => import('./UrlFetchModal'));
|
||||||
const CreateFileModal = dynamic(() => import('./CreateFileModal'));
|
const CreateFileModal = dynamic(() => import('./CreateFileModal'));
|
||||||
@@ -54,6 +55,7 @@ const FileSelect = ({
|
|||||||
showCreateFile = true,
|
showCreateFile = true,
|
||||||
...props
|
...props
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
|
const { kbDetail } = useUserStore();
|
||||||
const { Loading: FileSelectLoading } = useLoading();
|
const { Loading: FileSelectLoading } = useLoading();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -109,7 +111,7 @@ const FileSelect = ({
|
|||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
})(),
|
})(),
|
||||||
uploadFiles([file], (percent) => {
|
uploadFiles([file], { kbId: kbDetail._id }, (percent) => {
|
||||||
if (percent < 100) {
|
if (percent < 100) {
|
||||||
setSelectingText(
|
setSelectingText(
|
||||||
t('file.Uploading', { name: file.name.slice(0, 20), percent }) || ''
|
t('file.Uploading', { name: file.name.slice(0, 20), percent }) || ''
|
||||||
|
@@ -31,7 +31,7 @@ const Kb = () => {
|
|||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { openConfirm, ConfirmModal } = useConfirm({
|
const { openConfirm, ConfirmModal } = useConfirm({
|
||||||
title: '删除提示',
|
title: '删除提示',
|
||||||
content: '确认删除该知识库?'
|
content: '确认删除该知识库?知识库相关的文件、记录将永久删除,无法恢复!'
|
||||||
});
|
});
|
||||||
const { myKbList, loadKbList, setKbList } = useUserStore();
|
const { myKbList, loadKbList, setKbList } = useUserStore();
|
||||||
|
|
||||||
|
@@ -79,7 +79,7 @@ export class GridFSStorage {
|
|||||||
return Promise.reject(`file not found`);
|
return Promise.reject(`file not found`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (String(file.metadata?.userId) !== this.uid) {
|
if (file.metadata?.userId !== this.uid) {
|
||||||
return Promise.reject(ERROR_ENUM.unAuthFile);
|
return Promise.reject(ERROR_ENUM.unAuthFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,6 +100,16 @@ export class GridFSStorage {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async deleteFilesByKbId(kbId: string) {
|
||||||
|
if (!kbId) return;
|
||||||
|
const bucket = this.GridFSBucket();
|
||||||
|
const files = await bucket
|
||||||
|
.find({ ['metadata.kbId']: kbId, ['metadata.userId']: this.uid }, { projection: { _id: 1 } })
|
||||||
|
.toArray();
|
||||||
|
|
||||||
|
return Promise.all(files.map((file) => this.delete(String(file._id))));
|
||||||
|
}
|
||||||
|
|
||||||
async download(id: string) {
|
async download(id: string) {
|
||||||
await this.findAndAuthFile(id);
|
await this.findAndAuthFile(id);
|
||||||
|
|
||||||
|
@@ -7,8 +7,13 @@ import { uploadImg, postUploadFiles } from '@/api/system';
|
|||||||
/**
|
/**
|
||||||
* upload file to mongo gridfs
|
* upload file to mongo gridfs
|
||||||
*/
|
*/
|
||||||
export const uploadFiles = (files: File[], percentListen?: (percent: number) => void) => {
|
export const uploadFiles = (
|
||||||
|
files: File[],
|
||||||
|
metadata: Record<string, any> = {},
|
||||||
|
percentListen?: (percent: number) => void
|
||||||
|
) => {
|
||||||
const form = new FormData();
|
const form = new FormData();
|
||||||
|
form.append('metadata', JSON.stringify(metadata));
|
||||||
files.forEach((file) => {
|
files.forEach((file) => {
|
||||||
form.append('file', file, encodeURIComponent(file.name));
|
form.append('file', file, encodeURIComponent(file.name));
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user