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

3

我知道我可以通过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 } );

除了文件之外,我的请求还包含一些文本属性,例如名称: 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);
    }
}

我卡在同一个问题上了,你找到解决办法了吗? - koder613
2个回答

1
根据 multer 文档,它无法访问其他附加字段的 req.body,如果你测试它,它会收到一个 undefined 值,那么一个不太完美但是功能正常的解决方案是,在文件上传后可以将其重命名如下。
  1. Add the native class fs for access to files option

    const fs = require('fs');
    
  2. In diskStorage configuration add the name you want, for example bla.png

    var storage = multer.diskStorage({
        destination: path.join('public/images/'),
        filename: function ( req, file, cb ) {          
            cb(null, 'bla.png');          
        }
    });
    
  3. The form with the text field for the custom name

    <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. Within the post path, once you have sent the file whose name will be bla.png, you can replace that name with the one in a field of the form by accessing 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';
    });
    

1

Multer是中间件,既可以填充req.body又可以存储文件。

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

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

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

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

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

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


你有找到更好的方法来做这件事吗? - koder613

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接