diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts index 5b6b715e4e..a5dc7f2a30 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/server.ts @@ -62,11 +62,21 @@ export class PluginFileManagerServer extends Plugin { return; } + if (!record.get('storageId')) { + return; + } + const storage = this.storagesCache.get(record.get('storageId')); + if (!storage) { + return; + } if (storage?.paranoid) { return; } const Type = this.storageTypes.get(storage.type); + if (!Type) { + return; + } const storageConfig = new Type(storage); const result = await storageConfig.delete([record as unknown as AttachmentModel]); if (!result[0]) { @@ -245,6 +255,15 @@ export class PluginFileManagerServer extends Plugin { ); }); Storage.afterDestroy((m, { transaction }) => { + for (const collection of this.db.collections.values()) { + if (collection?.options?.template === 'file' && collection?.options?.storage === m.name) { + throw new Error( + this.t( + `The storage "${m.name}" is in use in collection "${collection.name}" and cannot be deleted.`, + ) as any, + ); + } + } this.storagesCache.delete(m.id); this.sendSyncMessage( { diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/index.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/index.ts index afd5d2bcf0..355fb4ea00 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/index.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/index.ts @@ -10,7 +10,7 @@ import { isURL } from '@nocobase/utils'; import { StorageEngine } from 'multer'; import urlJoin from 'url-join'; -import { encodeURL, ensureUrlEncoded } from '../utils'; +import { encodeURL, ensureUrlEncoded, getFileKey } from '../utils'; export interface StorageModel { id?: number; @@ -42,6 +42,10 @@ export abstract class StorageType { abstract make(): StorageEngine; abstract delete(records: AttachmentModel[]): [number, AttachmentModel[]] | Promise<[number, AttachmentModel[]]>; + getFileKey(record: AttachmentModel) { + return getFileKey(record); + } + getFileData?(file: { [key: string]: any }): { [key: string]: any }; getFileURL(file: AttachmentModel, preview?: boolean): string | Promise { // 兼容历史数据 diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/s3.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/s3.ts index 98113ce410..9e63d62478 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/s3.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/storages/s3.ts @@ -7,11 +7,11 @@ * For more information, please refer to: https://www.nocobase.com/agreement. */ -import { S3Client, DeleteObjectCommand } from '@aws-sdk/client-s3'; +import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3'; import crypto from 'crypto'; import { AttachmentModel, StorageType } from '.'; import { STORAGE_TYPE_S3 } from '../../constants'; -import { cloudFilenameGetter, getFileKey } from '../utils'; +import { cloudFilenameGetter } from '../utils'; export default class extends StorageType { static defaults() { @@ -87,8 +87,8 @@ export default class extends StorageType { async delete(records: AttachmentModel[]): Promise<[number, AttachmentModel[]]> { const { Deleted } = await this.deleteS3Objects( this.storage.options.bucket, - records.map((record) => getFileKey(record)), + records.map((record) => this.getFileKey(record)), ); - return [Deleted.length, records.filter((record) => !Deleted.find((item) => item.Key === getFileKey(record)))]; + return [Deleted.length, records.filter((record) => !Deleted.find((item) => item.Key === this.getFileKey(record)))]; } } diff --git a/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts b/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts index bdf312992e..a5d6b1334d 100644 --- a/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts +++ b/packages/plugins/@nocobase/plugin-file-manager/src/server/utils.ts @@ -9,6 +9,7 @@ import { uid } from '@nocobase/utils'; import path from 'path'; +import urlJoin from 'url-join'; export function getFilename(req, file, cb) { const originalname = Buffer.from(file.originalname, 'binary').toString('utf8'); @@ -27,7 +28,7 @@ export const cloudFilenameGetter = (storage) => (req, file, cb) => { }; export function getFileKey(record) { - return [record.path.replace(/^\/|\/$/g, ''), record.filename].filter(Boolean).join('/'); + return urlJoin(record.path, record.filename).replace(/^\//, ''); } export function ensureUrlEncoded(value) {