NodeJS-multer-根据请求属性更改文件名

时间:2018-11-26 18:27:51

标签: javascript node.js file-upload multer

我知道我可以通过存储对象使用multer更改文件名,如下所示:

const storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, process.env.UPLOAD_DIR);
    },
    filename: (req, file, cb) => {
        cb(null, 'bla.png');
    }
});
const upload = multer({ storage: storage } );

我的请求除了拥有文件外,还包含一些文本属性,例如name: myPic.png

是否可以根据其他请求属性或在控制器内动态更改文件名,如下所示:

filename: (req, file, cb) => {
     cb(null, `${req.body.name}.png`);
}

router.post('/upload', upload.single('pic'), myController.upload);

/* in controller */
upload = async (req: Request, res: Response) => {
    try {

        /* change the filename of multer here? */

    } catch (err) {
        winston.error(`Error while uploading: ${err.message}`);
        winston.error(`Stack trace: ${err.stack}`);
        sendJSONResponse(res, err, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

2 个答案:

答案 0 :(得分:0)

Multer是填充req.body并存储文件的中间件。

此外,当到达filename()函数时,不能保证文本字段将填充在req.body中,因为它取决于客户端sends them in的顺序(请参阅最后的注释) )。

据我所见,您有两个选择:

1)在multer上载中间件完成其工作并填充req.bodyreq.file之后,重命名上载的文件。因此,在您的控制器上传中间件中,您将执行以下操作:

if (req.file) {
    fs.renameSync(req.file.path, req.file.destination + req.body.name);
}

2)将请求正文文本字段更改为查询参数。然后,在filename()内部,您可以执行req.query.name

缺点:这不是一个非常RESTful的设计,但是对您来说也许并不那么重要。

答案 1 :(得分:0)

根据 multer 文档,它无权访问 req.body 以获取其他附加字段,如果您对其进行测试,它会收到 undefined 值,那么下面是一个不太完美但功能齐全的解决方案,文件上传后,您可以按如下方式重命名。

  1. 添加原生类 fs 以访问文件选项

    const fs = require('fs');
    
  2. diskStorage 配置中添加您想要的名称,例如 bla.png

    var storage = multer.diskStorage({
        destination: path.join('public/images/'),
        filename: function ( req, file, cb ) {          
            cb(null, 'bla.png');          
        }
    });
    
  3. 带有自定义名称文本字段的表单

    <form action="/upload" enctype="multipart/form-data" method="POST">
        <input type="file" accept="image/*" name="photo" >
        <br><!--here is the custom file name-->
        <input type="text" name="file_name">
        <br> 
        <button type="submit">Send</button>
    </form>
    
  4. 在发布路径中,一旦您发送了名称为 bla.png 的文件,您可以通过访问 req.body.field_name

    将该名称替换为表单字段中的名称
    router.post('/upload', upload.single('photo'), (req, res) => {
        //Here change the file name bla.png for the new value in req.body.field_name + original ext of file
        fs.renameSync(req.file.path, req.file.path.replace('bla.png', 
        req.body.field_name + path.extname(req.file.originalname)));
        if(req.file) { 
            res.json(req.file);
        }
        else throw 'error';
    });