nodejs保存上传的文件



我有一个应用程序,在该应用程序中,我想使用一些文件上传机制。

我的要求是:

上传文件后,其名称将更改为唯一的东西,例如uuid4()。我将稍后将此名称存储在数据库中。

我写了类似的东西,但是我有几个问题:

const multer = require('multer');
const upload = multer();
router.post('/', middleware.checkToken, upload.single('file'), (req,res,next)=>{
    // key:
    // file : "Insert File Here"
    console.log("req:");
    console.log(req.file);
    const str = req.file.originalname
    var filename = str.substring(0,str.lastIndexOf('.'));
    // I will use filename and uuid for storing it in the database
    // I will generate unique uuid for the document and store the document
    // with that name
    var extension = str.substring(str.lastIndexOf('.') + 1, str.length);
    // HERE!
    res.status(200).json();
})

我已经看到将其存储在diskstorage中的示例:

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, '/tmp/my-uploads')
    },
    filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now())
  }
})
var upload = multer({ storage: storage })

但是,据我了解,这是API呼叫之外的配置。这意味着我每次调用此API都无法修改它。我想为文件分配不同的名称,我需要该名称(uuid)将该名称保存在数据库中。

如何保留此类功能?

感谢@rashomon和@eimran Hossain Eimon,我解决了问题。如果有人想知道解决方案,这里是:

const multer = require('multer');
var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        // the file is saved to here
        cb(null, '/PATH/TO/FILE')
    },
    filename: function (req, file, cb) {
        // the filename field is added or altered here once the file is uploaded
        cb(null, uuidv4() + '.xlsx')
    }
})
var upload = multer({ storage: storage })

router.post('/', middleware.checkToken, upload.single('file'), (req,res,next)=>{
    // the file is taken from multi-form and the key of the form must be "file"
    // visible name of the file, which is the original, uploaded name of the file
    const name = req.file.originalname;
    // name of the file to be stored, which contains unique uuidv4
    const fileName = req.file.filename;
    // get rid of the extension of the file ".xlsx"
    const file_id = fileName.substring(0, fileName.lastIndexOf('.'));
    // TODO
    // Right now, only xlsx is supported
    const type = "xlsx";
    const myObject = new DatabaseObject({
        _id : new mongoose.Types.ObjectId(),
        file_id: file_id,
        name : name,
        type: "xlsx"
    })
    myObject .save()
    .then(savedObject=>{
        // return some meaningful response
    }).catch(err=>{
        // return error response
    })
})

这解决了我当前的问题。感谢您的帮助。对于将来的改进,我将添加错误案例:

  • 如果UUIDV4返回已经存在的ID(我认为由于对象包含某些时间戳数据,这是极不可能的),请重新运行重命名函数。

  • 如果保存到数据库存在错误,我应该删除上传的文件以避免将来的冲突。

如果您也有解决这些问题的解决方案,我非常感谢。

我想你错了...你说

我每次调用此api时都无法修改它。

但实际上,每次为每个文件都调用filename。让我解释一下代码的这一部分...

filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now())
  }

在这里查看callback函数(由cb表示):

  • 回调函数中的第一个参数 null就像 justnument 。您始终将null作为回调函数中的第一个参数传递。请参阅此参考
  • 第二个参数确定在destination文件夹中应命名的文件。因此,您可以在这里指定任何功能,每次都可以返回 unique fileName。

因为您正在使用猫鼬...我认为,如果您使用架构中的mongoose method(在其中保存文件路径)中实现function uniqueFileName()并将其调用在路由处理程序中,那会更好。了解更多

  1. 无需。因为您正在使用时间戳。

  2. 如果保存到数据库中的错误,您可以使用此代码删除上传文件,以避免将来的冲突。尝试以下操作:

    const multer = require('multer');
    const fs = require('fs'); // add this line
    var storage = multer.diskStorage({
        destination: function (req, file, cb) {
            // the file is saved to here
            cb(null, '/PATH/TO/FILE')
        },
        filename: function (req, file, cb) {
            // the filename field is added or altered here once the file is uploaded
            cb(null, uuidv4() + '.xlsx')
        }
    })
    var upload = multer({ storage: storage })
    
    router.post('/', middleware.checkToken, upload.single('file'), (req,res,next)=>{
        // the file is taken from multi-form and the key of the form must be "file"
        // visible name of the file, which is the original, uploaded name of the file
        const name = req.file.originalname;
        // name of the file to be stored, which contains unique uuidv4
        const fileName = req.file.filename;
        // get rid of the extension of the file ".xlsx"
        const file_id = fileName.substring(0, fileName.lastIndexOf('.'));
        // TODO
        // Right now, only xlsx is supported
        const type = "xlsx";
        const myObject = new DatabaseObject({
            _id : new mongoose.Types.ObjectId(),
            file_id: file_id,
            name : name,
            type: "xlsx"
        })
        myObject .save()
        .then(savedObject=>{
            // return some meaningful response
        }).catch(err=>{
            // add this
            // Assuming that 'path/file.txt' is a regular file.
            fs.unlink('path/file.txt', (err) => {
               if (err) throw err;
               console.log('path/file.txt was deleted');
            });
        })
    })
    

另请参见Nodejs文件系统doc

最新更新