使用AdminJS向MongoDB上传图片失败的问题求助
AdminJS 图片上传配置问题排查与解决
问题背景
尝试使用AdminJS向MongoDB的StartUp模型上传Logo图片,相关代码如下:
ifile.mjs
import { mongoose } from 'mongoose'; export const ImageSchema = new mongoose.Schema({ mime: {type: String, required: true}, }); const Image = mongoose.model("Image", ImageSchema); export default Image;
startup.mjs
import { mongoose } from 'mongoose'; const startupSchema = new mongoose.Schema( { Logo: { type: Buffer }, StartUp_Name: { type: String, required: true }, Idea_Description:{ type: String, }, }, { timestamps: {createdAt: 'created_at', updatedAt: 'updated_at'} } ); const StartUp = mongoose.model("StartUp", startupSchema); export default StartUp;
app.mjs
// All required dependencies import uploadFeature from '@adminjs/upload'; import StartUp from './collection/startup.mjs' import Image, { ImageSchema } from './collection/ifile.mjs' dotnev.config("./.env") const PORT = process.env.PORT || 3002 const start = async () => { const MongoStore = MongoDBStore(session); connectDB() const HomePage = { name: 'Home Page', icon: 'Home'} const admin = new AdminJS({ resources: [ { resource: StartUp, options: { navigation: HomePage, bio: { isVisible: { edit: true, show: true, list: true, filter: true, }, }, properties: { // mime: { type: 'string',}, // image: { isVisible: true, } }, actions: { uploadFile: { provider: { aws: S3 }, validation: { mimeTypes: ['image/png', 'application/pdf'] }, properties: { key: S3.accessKeyId, }, }, // features:[ // uploadFeature({ // provider: { aws: S3 }, // validation: { mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'] }, // properties: { // key: process.env.AWS_ACCESS_KEY_SECRET // mimeType: 'mimeTypes', // }, // }), // ] }, editProperties: ['StartUp_Name', 'Idea_Description'], filterProperties: ['StartUp_Name', 'Idea_Description', 'created_at'], showProperties: ['StartUp_Name', 'Idea_Description'], }, ], rootPath: "/admin", }, }) const adminRouter = AdminJSExpress.buildRouter(admin) app.use(cors()); app.use(admin.options.rootPath, adminRouter) app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.listen(PORT, () => { console.log(`AdminJS started on http://localhost:${PORT}${admin.options.rootPath}`) }) start()
遇到的问题
- 使用
uploadFile自定义action时,右上角上传按钮点击无实际功能; - 启用注释的
uploadFeature配置时,触发TypeError:
............./backend/node_modules/@adminjs/upload/build/features/upload-file/utils/bundle-component.js:7 return loader.add(componentName, componentPath); ^ TypeError: Cannot read properties of undefined (reading 'add') at bundleComponent (............./backend/node_modules/@adminjs/upload/build/features/upload-file/utils/bundle-component.js:7:19) at uploadFeature (............./backend/node_modules/@adminjs/upload/build/features/upload-file/upload-file.feature.js:63:31) at uploadFileFeature (............./backend/node_modules/@adminjs/upload/build/features/upload-file/upload-file.feature.js:102:12) at start (............./backend/app.mjs:184:17) at ............./backend/app.mjs:446:1 Node.js v18.16.0 [nodemon] app crashed - waiting for file changes before starting...
尝试本地文件系统存储时也出现相同错误,配置如下:
features: [ uploadFeature({ provider: localProvider, validation: { mimeTypes: ['image/png', 'application/pdf'],}, options: { key: 323, bucket: './public/files', s3Key: 'uploadFeature', }, }), ],
解决步骤
问题1:uploadFile按钮无功能
uploadFile是自定义action,当前仅定义了元数据,未实现文件上传的核心处理逻辑,因此点击无反应。AdminJS官方推荐使用uploadFeature实现文件上传,直接放弃该自定义action方案。
问题2:uploadFeature触发TypeError的解决
1. 修正Schema字段
StartUp模型需同时存储文件的Buffer数据和MIME类型,修改startup.mjs:
const startupSchema = new mongoose.Schema( { Logo: { type: Buffer }, Logo_mime: { type: String }, // 新增MIME类型存储字段 StartUp_Name: { type: String, required: true }, Idea_Description:{ type: String, }, }, { timestamps: {createdAt: 'created_at', updatedAt: 'updated_at'} } );
2. 修正uploadFeature配置位置
之前将features数组放在actions对象内部,属于错误位置。features是resource配置的顶级属性,需与options同级。
3. 正确配置uploadFeature与依赖
首先安装必要依赖:
npm install @adminjs/express express-formidable dotenv
然后修改app.mjs核心配置:
// 修正dotenv导入与配置 import dotenv from 'dotenv'; dotenv.config({ path: './.env' }); // 导入本地存储provider(使用S3则替换为对应配置) import { localProvider } from '@adminjs/upload'; // 修正AdminJS资源配置 const admin = new AdminJS({ resources: [ { resource: StartUp, // 正确放置features数组 features: [ uploadFeature({ provider: localProvider, validation: { mimeTypes: ['image/png', 'image/jpg', 'image/jpeg'] }, properties: { key: 'Logo', // 对应Schema中的Buffer字段 mimeType: 'Logo_mime', // 对应新增的MIME字段 }, options: { bucket: './public/files', // 本地存储路径,需确保目录存在且有读写权限 // 若使用S3,替换为以下配置: // bucket: process.env.AWS_S3_BUCKET, // region: process.env.AWS_REGION, // accessKeyId: process.env.AWS_ACCESS_KEY_ID, // secretAccessKey: process.env.AWS_ACCESS_KEY_SECRET, }, }), ], options: { navigation: HomePage, // 将Logo字段加入编辑和展示属性 editProperties: ['StartUp_Name', 'Idea_Description', 'Logo'], filterProperties: ['StartUp_Name', 'Idea_Description', 'created_at'], showProperties: ['StartUp_Name', 'Idea_Description', 'Logo'], }, }, ], rootPath: "/admin", }) // 修正adminRouter生成,添加formidable支持 const adminRouter = AdminJSExpress.buildRouter(admin, { // 可选:添加认证逻辑,无需认证可返回null authenticate: async (email, password) => { if (email === process.env.ADMIN_EMAIL && password === process.env.ADMIN_PASSWORD) { return { email }; } return null; }, formidableOptions: {}, // 必须配置,用于处理文件上传 })
4. 修复其他语法错误
- 修正
dotnev为dotenv并正确导入; - 确保
connectDB函数正确实现MongoDB连接; - 确保
session、cors、bodyParser等依赖已正确导入。
验证
启动服务后,进入AdminJS的StartUp编辑页面,即可看到Logo字段的文件上传控件,点击后可弹出文件选择窗口完成上传。
内容的提问来源于stack exchange,提问作者Yash Maheshwari
相关产品推荐
相关产品推荐

