首页 > 解决方案 > node express with multer 如何在运行时选择 MemoryStorage 或 DiskStorage

问题描述

您好我正在尝试在运行时选择存储,因为我还添加了一个中间件来获取之前的内容大小。

我在其他地方有一个导出的枚举:

export enum Storage {
    DISK,
    MEMORY
}

中间件 checkHeader :

const checkHeader = (req :any , res: any , next:any ) => {
    console.log('content-length :',req.headers['content-length']);
    const sizeContent =  req.headers['content-length'];
    if (!sizeContent || Number(sizeContent) ==0 ) {
        res.send(400).end();
        return;
    }
    const sizeKo = Number(sizeContent)/1024 >5000 ;
    console.log('size : (KO) ',sizeKo);
    res.locals.storage = Number(sizeContent)/1024 >5000 ? Storage.DISK:Storage.MEMORY;
    next();
};

制作multer中间件

const createUpload = (_req: Request, res: Response, _next:any) :any   =>{
    let storage;
    if (res.locals) {console.log('in createupload : ' , res.locals.storage);}
    else return _next;
    if (res.locals.storage === Storage.DISK){
        storage = multer.diskStorage({
            destination: function (_req, _file, cb) {
              cb(null, './uploads/');
            },
          
            filename: function (_req: any, file: any, cb: any) {
              cb(null, file.originalname);
            },
          });
    }
    else {
        storage = multer.memoryStorage();
    }
    return multer({ storage: storage, fileFilter: fileFilter }).any();
  };

创建路线

const router = express
  .Router()
  .get('/', controller.all)
  .post('/', controller.create)
  .get('/:id', controller.byId)
  .get('/:id/contractors', controller.getContractors)
  .post('/:id/contractors', controller.addContractors)
  .post('/:id/documents', checkHeader ,createUpload, controller.addDocument);

它不起作用,我想这是因为 createUpload 不返回,即示例,

multer({storage : multer.memoryStorage()}).any() 

但它返回返回它的函数!但是我不得不把它写成一个中间件函数,即 (req,res,next)=>return一个中间件,以便让它通过中间件链....

我不知道如何为这个用例编写代码,...

预先感谢

标签: node.jsexpressmulter

解决方案


最后,我得到了一个解决方法:

const fileFilter = (_req: any, file: any, cb: any) => {
  if (
    file.mimetype === 'image/jpg' ||
    file.mimetype === 'image/jpeg' ||
    file.mimetype === 'image/png' ||
    file.mimetype === 'application/pdf'
  ) {
    cb(null, true);
  } else {
    cb(new Error('not type pdf or jpg/jpeg or png'), false);
  }
};

const setUploadDest = (req :any , res: any , next:any ) => {
    console.log('content-length :',req.headers['content-length']);
    const sizeContent =  req.headers['content-length'];
    res.locals.storage = Number(sizeContent)/1024 >5000 ? Storage.DISK:Storage.MEMORY;
    next();
};


const skipMemory = (_req :any , res: any , next:any ) => {
    if (res.locals.storage !== Storage.MEMORY){
        next('route');
    }
    else next();
};

const skipDisk = (_req :any , res: any , next:any ) => {
    if (res.locals.storage !== Storage.DISK){
        next('route');
    }
    else next();
};


const diskStorage = multer.diskStorage({
        destination: function (_req, _file, cb) {
            cb(null, './uploads/');
        },
        filename: function (_req: any, file: any, cb: any) {
            cb(null, file.originalname);
        }
});



const router = express
  .Router()
  .get('/', controller.all)
  .post('/', controller.create)
  .get('/:id', controller.byId)
  .get('/:id/contractors', controller.getContractors)
  .post('/:id/contractors', controller.addContractors)
  .use('/:id/documents',setUploadDest)
  .post('/:id/documents', skipMemory , multer({storage : multer.memoryStorage(), fileFilter:fileFilter}).any() , controller.addDocument)
  .post('/:id/documents', skipDisk, multer({storage : diskStorage, fileFilter :fileFilter}).any() , controller.addDocument);

意味着我复制了后路由器,每个都附加到一个 multer 存储构造函数。我通过添加一个“跳过”中间件来控制路由,如果存储条件不满足,它将发送到另一条路由......


推荐阅读