Я настраиваю новый сервер и хочу поддерживать расширенную функцию загрузки. Во-первых, мне нужно проверить файл (тип файла, размер файла, максимальное количество) и, наконец, загрузить его в какое-либо место назначения. Я пробовал что-то с koa-multer, но не могу получить ошибки проверки multer.
multer.js
const multer = require('koa-multer')
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads/')
},
filename: function (req, file, cb) {
var fileFormat = (file.originalname).split('.')
cb(null, file.fieldname + '_' + Date.now() + '.' + fileFormat[fileFormat.length - 1])
}
})
const fileFilter = (req, file, cb) => {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true)
} else {
cb(new Error('This is not image file type'), false)
}
}
const upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 1,
files: 5
},
fileFilter: fileFilter
})
module.exports = upload
router.js
const Router = require('koa-router')
const multer = require('../middlewares/multer')
const auth = require('../middlewares/auth')
const controller = require('../controllers').userController
const schemas = require('../schemas/joi_schemas')
const validation = require('../middlewares/validation')
const router = new Router()
const BASE_URL = `/users`
router.post(BASE_URL, auth , validation(schemas.uPOST, 'body'), controller.
addUser)
router.put(`${BASE_URL}/:id`, auth , multer.single('logo')(ctx, (err) => {
if (err) {
ctx.body = {
success: false,
message: 'This is not image file'
}
}
}), controller.editUser)
router.delete(`${BASE_URL}/:id`, auth , controller.deleteUser)
module.exports = router.routes()
Как я могу решить проблему загрузки наилучшим образом для долгосрочного обслуживания кода?
🤔 А знаете ли вы, что...
Node.js обладает большой активной сообществом разработчиков и поддерживается множеством компаний.
промежуточное ПО koa похоже на вложенный обратный вызов, вы должны ловить «next()», а не после multer
router.put(`${BASE_URL}/:id`, auth , async (ctx, next) => {
try{
await next()
} catch(err) {
ctx.body = {
success: false,
message: 'This is not image file'
}
}
}, multer.single('logo'), controller.editUser)
но вы сделаете это, он также поймает ошибки controller.editUser, которые не были обнаружены самим контроллером.
Самый простой подход к загрузке файлов следующий (предположим, что в форме есть поле для загрузки файлов с именем avatar
):
const Koa = require('koa')
const mime = require('mime-types')
const Router = require('koa-router')
const koaBody = require('koa-body')({multipart: true, uploadDir: '.'})
const router = new Router()
router.post('/register', koaBody, async ctx => {
try {
const {path, name, type} = ctx.request.files.avatar
const fileExtension = mime.extension(type)
console.info(`path: ${path}`)
console.info(`filename: ${name}`)
console.info(`type: ${type}`)
console.info(`fileExtension: ${fileExtension}`)
await fs.copy(path, `public/avatars/${name}`)
ctx.redirect('/')
} catch(err) {
console.info(`error ${err.message}`)
await ctx.render('error', {message: err.message})
}
})
Обратите внимание, что в этом примере используется Асинхронные функции, что позволяет использовать чистый код со стандартным блоком try-catch для обработки исключений.
Вы можете использовать один из двух вариантов:
Первый заключается в добавлении функции обратного вызова в конец маршрута.
const multer = require('@koa/multer')
//Options to limit file size and file extension
const upload = multer({
dest: '../avatars',
limits: {
fileSize: 1024*1024
},
fileFilter(ctx, file, cb) {
if (!file.originalname.match(/\.(jpg|jpeg|png)$/)) {
return cb(new Error('Please upload a World document'))
}
cb(undefined, true)
}
})
//The last callback should handle the error from multer
router
.post('/upload', upload.single('upload'), async (ctx) => {
ctx.status = 200
}, (error, ctx) => {
ctx.status = 400
ctx.body = error.message
})
})
Второй вариант — добавить try/catch перед вызовом промежуточного ПО multer:
router
.post('/upload', async (ctx, next) => {
try {
await next()
ctx.status = 200
} catch (error) {
ctx.status = 400
ctx.body = error.message
}
}, upload.single('upload'), async ctx => {ctx.status = 200})
В последнем случае, если исключение будет выброшено в multer, оно будет обработано try/catch в предыдущем вызове await next().