Nodejs сохранить загруженный файл - PullRequest
0 голосов
/ 12 марта 2019

У меня есть приложение, и в этом приложении я хочу использовать механизм загрузки файлов.

Мое требование:

Как только файл загружен, его имя будет изменено на что-то уникальное, например, 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();

})

Я видел примеры его хранения на диске:

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), чтобы сохранить это имя в базе данных.

Как сохранить такую ​​функциональность?

Ответы [ 3 ]

1 голос
/ 12 марта 2019

Благодаря @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 возвращает идентификатор, который уже существует (я считаю, что это очень маловероятно, так как объект содержит некоторые временные метки), перезапуститефункция переименования.

  • В случае ошибки при сохранении в базу данных, я должен удалить загруженный файл, чтобы избежать будущих конфликтов.

Если у вас есть решения для этих проблем, я очень ценю.

0 голосов
/ 13 марта 2019
  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 File System Doc

0 голосов
/ 12 марта 2019

Я думаю, вы ошиблись ... вы сказали, что

Я не могу изменять его каждый раз, когда вызываю этот API.

Но на самом деле, filename вызывается каждый раз для каждого файла.Позвольте мне объяснить эту часть кода ...

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

Здесь рассмотрим функцию callback (обозначается cb):

  • 1-й аргумент null inфункция обратного вызова похожа на соглашение .Вы всегда передаете null в качестве первого аргумента в функции обратного вызова. См. Этот справочник
  • 2-й аргумент определяет, как должен называться файл в папке destination. Итак, здесь вы можете указать любую функцию, которая может каждый раз возвращать вам уникальное имя файла.

Поскольку вы используете мангуст ... Я думаю,было бы лучше, если бы вы реализовали function uniqueFileName(), используя mongoose method в своей схеме (в которой вы хотите сохранить путь к файлу), и вызвали его в своем обработчике маршрута. Узнать больше

...