使用multer&;node.js

使用multer&;node.js,node.js,multer,Node.js,Multer,大家好 我正在尝试使用multer上传多部分formdata。文件上载到正确的目录,但随后程序执行停止。我正在和邮递员测试路线。中间件模块是一个自动执行的函数,我将其传递给我的路由,但是在文件保存后,控制台只显示“undefined”,postman throws无法获得响应 文件上传完成后,应该移动到“updateRules”中间件来验证表单 有趣的是我的“fileUpload.js”中的“console.log(返回前)”在我更改和保存文件后立即执行 我不知道这是否是一个自我调用的函数,但是

大家好

我正在尝试使用multer上传多部分formdata。文件上载到正确的目录,但随后程序执行停止。我正在和邮递员测试路线。中间件模块是一个自动执行的函数,我将其传递给我的路由,但是在文件保存后,控制台只显示“undefined”,postman throws无法获得响应

文件上传完成后,应该移动到“updateRules”中间件来验证表单

有趣的是我的“fileUpload.js”中的“console.log(返回前)”在我更改和保存文件后立即执行

我不知道这是否是一个自我调用的函数,但是我对Node是新手,我只是在学习教程。auth&updateRules中间件工作正常,但在文件上载到指定路径后,程序执行将挂起。此外,user.id是一个数字,例如6

下面是我的路线

const router = require('express').Router()

const { validate } = require('../validators')
const { update } = require('../controllers/userController')
const { auth } = require('../middleware/auth')
const { rules : updateRules } = require('../validators/user/update')
const { userFile }  = require('../middleware/fileUpload')

router.post('/update', [auth, userFile, updateRules, validate], update)

module.exports = router
这是我的fileUpload.js中间件

const multer = require('multer')
const fs = require('fs')
const path = require('path')

exports.userFile = ((req,res, next) => {

  const getFileType = file => {
    const mimeType = file.mimetype.split('/')
    return mimeType[mimeType.length - 1]
  }

  const generateFilename = (req, file, cb) => {
    console.log(file.originalName)
    const extension = getFileType(file)

    const filename = Date.now() + '-' + Math.round(Math.random() * 1E9 ) + '.' + extension
    cb(null,file.fieldname + '-' + filename)
  }

  const fileFilter = (req, file, cb) => {

    const extension = getFileType(file)

    const allowedType = /jpeg|jpg|png/

    const passed = allowedType.test(extension)

    if(passed){
      return cb(null, true)
    }

    return cb(null, false)
  }

  const storage = multer.diskStorage({
 
    destination: function(req, file, cb) {
  
      const { id } = req.user
      const dest = `./uploads/user/${id}` 

      fs.access(dest, (error) => {
    
        // if folder doesnt exist
        if(error) {
          console.log("folder doesnt exist")
          return fs.mkdir(dest, {recursive: true} ,(error) => {            
            cb(error, dest)
          })
        } else {
          console.log("folder exists")
          fs.readdir(dest, (error, files) => {
            if(error) throw error

            for(const file of files) {
              fs.unlink(path.join(dest, file), error => { if(error) throw error } )
            }
          })

          return cb(null, dest)
        } 
      })
    },

    filename: generateFilename
  })
  console.log("before return")
  return  multer({storage, fileFilter}).single('avatar')
})()
我还尝试导出存储和文件过滤器函数,从路由器调用multer,但结果是一样的

route.js

const multer = require('multer')
const { storage, fileFilter }  = require('../middleware/fileUpload')

router.post('/update', 
[auth, multer({storage, fileFilter}).single('avatar'), 
updateRules, validate], update)

在路由器中,您需要喜欢在本例中所做的

router.put('/',multer({
    storage: storage,
    limits: {
        fileSize: 1000 * 1 * 3000
    }
}).single('productPic') //For single image and for multiple you can user array

在路由器中,您需要喜欢在本例中所做的

router.put('/',multer({
    storage: storage,
    limits: {
        fileSize: 1000 * 1 * 3000
    }
}).single('productPic') //For single image and for multiple you can user array

在我看来,在
fileUpload.js
中使用iLife是它崩溃的原因,当multer将文件保存到磁盘时,这是一个异步操作,因为multer实际保存文件需要几微秒,然后调用
next()
因为您使用的是IIFE,所以您的调用堆栈不会等待multer操作,而是继续运行

其次,您的这种方法不是一种理想的方法/至少不是一种推荐的方法,也许您的项目需要它,但是下面是我如何在我的项目中进行multer配置的方法

const multer = require("multer");

/* Custom Multer Filter */
const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith('image')) {
    cb(null, true);
  } else {
    cb(new Error('Not an image! Please upload only images.'), false);
  }
};

/* Multer storage */
const multerStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'public/img/');
  },
  filename: (req, file, cb) => {
    const ext = file.mimetype.split('/')[1];
    cb(null, `My-Custom-File-Prefixer.${ext}`);
  }
});

/* Endpoint Object For Single File */
const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter
});

/* Endpoint Object For Array of Files */
const MultiFileUpload = multer({
  storage: multerStorage,
  limits: { fileSize: 2000000 }, // In bytes: 2000000 bytes = 2 MB
  fileFilter: ImageFilter,
});




//Use 'uploadSingle' if there is just one File
exports.uploadSingle = upload.single('photo');
/* replace 'Photo' with the filed containing the single image */

/*Use 'arrayOfFile' if there are multiple fields containing files and set the limit of each field */

exports.arrayOfFile = MultiFileUpload.fields([
  { name: "albumCover", maxCount: 1 },
  { name: "albumImages", maxCount: 5 },
]);


然后在我的路由器上,如果我的请求只有一个文件,我会使用
uploadSingle
,如果我的请求在多个字段上有多个文件,我会使用
arrayOfFile
,在我看来,在
fileUpload.js
中使用iLife是它崩溃的原因,您可以看到,当multer将文件保存到磁盘时,这是一个异步操作,因为multer需要几微秒的时间来实际保存文件,然后调用
next()
,因为您使用的是iLife,所以您的调用堆栈不会等待multer操作,而是继续

其次,您的这种方法不是一种理想的方法/至少不是一种推荐的方法,也许您的项目需要它,但是下面是我如何在我的项目中进行multer配置的方法

const multer = require("multer");

/* Custom Multer Filter */
const multerFilter = (req, file, cb) => {
  if (file.mimetype.startsWith('image')) {
    cb(null, true);
  } else {
    cb(new Error('Not an image! Please upload only images.'), false);
  }
};

/* Multer storage */
const multerStorage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'public/img/');
  },
  filename: (req, file, cb) => {
    const ext = file.mimetype.split('/')[1];
    cb(null, `My-Custom-File-Prefixer.${ext}`);
  }
});

/* Endpoint Object For Single File */
const upload = multer({
  storage: multerStorage,
  fileFilter: multerFilter
});

/* Endpoint Object For Array of Files */
const MultiFileUpload = multer({
  storage: multerStorage,
  limits: { fileSize: 2000000 }, // In bytes: 2000000 bytes = 2 MB
  fileFilter: ImageFilter,
});




//Use 'uploadSingle' if there is just one File
exports.uploadSingle = upload.single('photo');
/* replace 'Photo' with the filed containing the single image */

/*Use 'arrayOfFile' if there are multiple fields containing files and set the limit of each field */

exports.arrayOfFile = MultiFileUpload.fields([
  { name: "albumCover", maxCount: 1 },
  { name: "albumImages", maxCount: 5 },
]);


然后在我的路由器上,如果我的请求只有一个文件,我会使用
uploadSingle
,如果我的请求在多个字段上有多个文件,我会使用
arrayOfFile
,我设法找到了一个answew。我的updateRules应该用括号来调用

感谢您的帮助和投入

我决定遵循你的模式,尼桑的维斯普特

这比自调用函数更干净

 router.post('/update', [auth, uploadSingle, updateRules(), validate ], update)

我设法找到了一个answew人。我的updateRules应该用括号来调用

感谢您的帮助和投入

我决定遵循你的模式,尼桑的维斯普特

这比自调用函数更干净

 router.post('/update', [auth, uploadSingle, updateRules(), validate ], update)


但这将如何影响我的fileUpload.js在导出内容和如何在路由内部导入方面的表现呢?它是否应该是一个自调用函数?您需要在实现存储函数的地方导出存储函数,并在定义路由的地方导入。我尝试过,但结果相同,请参阅我对问题所做的编辑。谢谢你的帮助,在你的存储功能中,你正在使用return multer({storage,fileFilter})。console.log(return before)之后的single('avatar')删除该行,然后再试一次。但是这会对我的fileUpload.js在导出什么和如何在路由内部导入方面产生什么影响呢?它是否应该是一个自调用函数?您需要在实现存储函数的地方导出存储函数,并在定义路由的地方导入。我尝试过,但结果相同,请参阅我对问题所做的编辑。感谢您在存储功能中提供的帮助,您正在使用return multer({storage,fileFilter}).single('avatar')after console.log(return before)删除该行,然后再试一次。我尝试了你的方法,但现在它甚至没有到达fileUpload.js。你如何在路由器中导入和调用它?Soory在非洲使用solongto Response im:)我共享的是通用代码,而不是工作代码,因为你必须根据项目要求修改它。用于在路由器上使用它
router.post('/update',uploadSingle,nextmiddleware)
用于处理单个文件,或者用
数组文件
替换
uploadSingle
用于处理多个文件我尝试了你的方法,但现在它甚至没有到达文件上传。js你如何在路由器中导入和调用它?在非洲使用Solong来响应im很好:)我共享的是一个通用代码,而不是工作代码,因为您必须根据项目要求对其进行修改。用于在路由器上使用它
router.post('/update',uploadSingle,nextmiddleware)
用于处理单个文件,或将
uploadSingle
替换为
arrayOfFile
用于处理多个文件如果您遵循这种模式,那么您甚至可以将整个Multer部分外包到一个单独的文件中,称之为
MulterMIddleware.js
,然后直接在路由器或任何其他设备上使用该文件有文件操作的中间件。。通过这种方式,您可以使您的所有中间件使用一个公共代码库来处理文件操作如果您遵循这种模式,那么您甚至可以将整个Multer部分外包到一个单独的文件中,并调用它,称之为
MulterMIddleware.js
,然后直接在您的路由器或您拥有该文件的任何其他中间件上使用该文件操作。。这样你就可以