我使用带有admin-bro的express和它的插件@admin-bro/upload在服务器上存储上传的图像文件。
使用以下AdminBroOptions初始化AdminBro对象
const adminBro = new AdminBro({
resources: [
{
resource: Furniture,
options: {
properties: {
'_id': {
isVisible: { list: false, filter: true, show: true, edit: false }
},
image: {
isVisible: false
}
}
},
features: [uploadFeature({
provider: { local: { bucket: path.join(__dirname, 'public', 'images', 'furniture') } },
properties: {
key: 'image.path',
bucket: 'image.folder',
mimeType: 'image.type',
size: 'image.size',
filename: 'image.filename',
file: 'uploadFile'
}
})]
}
],
branding: {
companyName: "Fran's Furniture"
}
})文件夹结构:
我遵循本教程主要是为了进行admin-bro配置:https://itnext.io/the-easiest-and-fastest-way-to-upload-files-in-node-js-4b49e0123190
我还在server.js文件中添加了app.use('/public', express.static('public'))
但我在上传图像文件时遇到了这个错误:
(node:153012) ExperimentalWarning: The fs.promises API is experimental
Error: EPERM: operation not permitted, mkdir 'F:'如果我将bucket属性更改为“public”:
provider: { local: { bucket: 'public' } }弹出以下错误(请注意,'public‘文件夹位于F:/而不是F:/path-to-project- folder中:
(node:163580) ExperimentalWarning: The fs.promises API is experimental
Error: EXDEV: cross-device link not permitted, rename 'C:\Users\Lenovo\AppData\Local\Temp\upload_4ca3c78a0517022a555815196102aee6' -> 'F:\public\5f98496b31e9d37efe9a2584\1.jpg'家具模型(如果需要):
const Image = new mongoose.Schema({
path: String,
type: String,
size: Number,
folder: String,
filename: String
})
const FurnitureSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
description: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
status: {
type: String,
enum: ['show', 'hide'],
default: 'show',
required: true
},
condition: {
type: String,
enum: ['new', 'used'],
required: true
},
image: Image,
category: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Category'
}
})所以在我看来,这个问题主要是由于存储桶选项的错误配置造成的。任何帮助都将不胜感激。
项目路径(如果需要):F:\Tutorials\Self-Projects\frans-node
发布于 2021-01-09 06:13:51
我自己编写了一个自定义的基本提供程序,并手动对文件执行copying+removing操作,从而解决了这个问题:
import { BaseProvider } from '@admin-bro/upload'
import { ActionContext, UploadedFile } from 'admin-bro'
import { promises, existsSync } from "fs"
import { resolve, dirname } from "path"
export class UploadProvider extends BaseProvider {
assetPath: string
constructor(bucket: string, assetPath: string) {
// it requires bucket as a parameter to properly pass it to other methods
super(bucket)
this.assetPath = assetPath
}
async upload(file: UploadedFile, key: string, context: ActionContext): Promise<any> {
const fullPath = resolve(this.assetPath, key)
const dirPath = dirname(fullPath)
if (!existsSync(dirPath)) {
await promises.mkdir(dirPath, { recursive: true })
}
await promises.copyFile(file.path, fullPath)
await promises.unlink(file.path)
return key
}
async delete(key: string, bucket: string, context: ActionContext): Promise<any> {
const filePath = resolve(this.assetPath, key)
if (existsSync(filePath)) {
await promises.unlink(filePath)
const dirPath = dirname(filePath)
const otherFiles = await promises.readdir(dirPath)
if (otherFiles && otherFiles.length == 0) {
await promises.rmdir(dirPath)
}
}
}
path(key: string, bucket: string, context: ActionContext): Promise<string> | string {
return "/" + bucket
}
}然后,像这样使用它:
// ...
const provider = new UploadProvider("assets", ASSET_PATH)
// ...
features: [
uploadFileFeature({ provider, ... })
]https://stackoverflow.com/questions/64557467
复制相似问题