在使用multer上传新文件之前,有什么方法可以调用函数来擦除所有文件?

时间:2019-04-03 10:28:23

标签: javascript node.js glob multer

我正在尝试在调用ereaseFiles()方法之前传递一个函数upload.array(),但我不知道该怎么做。

主要目标是发出放置请求,以便在上载新文件之前删除磁盘上与该对象相关的所有文件。

我尝试在diskStorage部分以及放置路由的回调中设置函数。在调用upload.array()方法之前,我什至尝试在函数本身中处理它。我已经尝试过兑现诺言,但这对我来说太难了。

//function to be called (this works)
function ereaseFiles(req) {
    glob("uploads/" + req.body.numeroScheda + "*", function (err, files) {
        for (const file of files) {
            fs.unlink(file, err => {
                if (err) throw err;
                console.log('successfully deleted files');
            });
        }
    });
}

//My multer setup:

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, './uploads/');

    },
    filename: function (req, file, cb) {
        cb(null, req.body.numeroScheda + "-" + file.originalname);
    }
});

const upload = multer({
    storage: storage, limits: {
        fileSize: 1024 * 1024 * 2,
    },
});

//MY EDIT PUT ROUTE
app.put("/immobili/:_id", upload.array('immaginePrincipale', 30), function (req, res) {

    const requestedId = req.params._id;
    const proprietaImmagini = req.files;
    const immagini = proprietaImmagini.map(function (immagine) {
        //console.log(immagine.path);
        return immagine.path;
    });

    Immobile.findOneAndUpdate(requestedId, {
        numeroScheda: req.body.numeroScheda,
        categoria: req.body.categoria,
        titolo: req.body.titolo,
        sottotitolo: req.body.sottotitolo,
        descrizione: req.body.descrizione,
        localita: req.body.localita,
        locali: req.body.locali,
        superficie: req.body.superficie,
        camere: req.body.camere,
        bagni: req.body.bagni,
        immagini: immagini,
    }, function (err, updatedImmobile) {
        if (err) return console.error(err);

        res.redirect("/immobili/" + requestedId);
    });
});

应该发生的是,在上传新文件之前,与对象(numeroScheda)关联的磁盘上的所有文件都会被删除,以保持文件存储的自动化和整洁。

编辑1:

我创建了一条可行的删除路线:

app.delete("/immobili/:_id", (req, res) => {

    const requestedId = req.params._id;

    Immobile.findOne({ _id: requestedId }, function (err, immobile) {
        if (err) return console.error(err);
        ereaseFiles(immobile);
    });

    Immobile.findOneAndRemove(requestedId, err => {
        if (err) console.error(err);
        else res.redirect('/immobili');
    });
});

函数ereaseFiles现在看起来像这样:

ereaseFiles = immobile => {
    glob("uploads/" + immobile.numeroScheda + "*", function (err, files) {
        for (const file of files) {
            fs.unlink(file, err => {
                if (err) throw err;
            });
        }
    });
cancellato = true;
}

我已经尝试使用中间件在编辑路径中实现此目的,

app.use("/immobili/:_id", function (req, res, next) {
    const requestedId = req.params._id;

    let timer = setInterval(() => {
        Immobile.findOne({ _id: requestedId }, (err, immobile) => {
            if (err) return console.error(err);
            ereaseFiles(immobile);
            console.log(this.cancellato);
            if (this.cancellato) {
                clearInterval(timer);
                next();
            }
        });
    }, 1000);
});

如果上传的图片多于或等于以前,但如果输出的图片少或带有奇怪的行为(有时会上传一些图片,有时不上传),则此方法有效。

2 个答案:

答案 0 :(得分:0)

您可以为此使用中间件。只需确保将中间件放置在放置请求处理程序之前即可。

app.use("/immobili/:_id", function(req,res,next){
eraseFiles(req);
let timer = setInterval(() => {
if(erased){
clearInterval(timer);
next();    
}
},100);

})

app.put("/immobili/:_id", upload.array('immaginePrincipale', 30), function (req, res) { ...

编辑1:

请将您的deleteFiles函数更改为:

function ereaseFiles(req) {
glob("uploads/" + req.body.numeroScheda + "*", function (err, files) {
    for (let i=0;i<files.length-1;i++) {
        fs.unlink(files[i], err => {
            if (err) throw err;
            console.log('successfully deleted files');
            if(i===files.length-1)
             erased = true;
        });
    }
});
}

编辑2:更改了很多内容。现在的方法是,您的路线将首先进入中间件。您的deleteFiles函数将被调用。如果擦除的变量不为true,则不会命中您的放置路线。当擦除文件功能完成时,它将被设置为true。为此,您必须在所有操作之前在文件中设置擦除= false。

答案 1 :(得分:0)

我赢了!解决方案是在next()函数上添加一个计时器,因为它触发得太早了,并且上载并混合了两者。谢谢大家的帮助!

我还添加了一个ereased变量,该变量在函数完成时关闭并打开。感谢Web先生。

如果有人遇到这个问题,这里就是答案,代码中有一些意大利语,希望无论如何都足够可读!

cancellaFoto = immobile => {
    cancellato = false;
    glob("uploads/" + immobile.numeroScheda + "*", function (err, files) {
        for (const file of files) {
            fs.unlink(file, err => {
                if (err) throw err;
            });
        }
    });
    cancellato = true;
}

app.use("/immobili/:_id", function (req, res, next) {

    const requestedId = req.params._id;

    Immobile.findOne({ _id: requestedId }, (err, immobile) => {
        if (err) return console.error(err);
        immobile.immagini = [];
        cancellaFoto(immobile);
        console.log(immobile.immagini);
        if (this.cancellato) {
            console.log(this.cancellato);
            return setTimeout(next, 500);
        } else {
            return console.log("Aborted");
        }
    });
});

//EDIT PUT ROUTE
app.put("/immobili/:_id", upload.array('immaginePrincipale', 30), function (req, res) {

    const requestedId = req.params._id;

    const proprietaImmagini = req.files;
    const immagini = proprietaImmagini.map(function (immagine) {
        //console.log(immagine.path);
        return immagine.path;
    });
    console.log(immagini);
    Immobile.findOneAndUpdate(requestedId, {
        numeroScheda: req.body.numeroScheda,
        categoria: req.body.categoria,
        titolo: req.body.titolo,
        sottotitolo: req.body.sottotitolo,
        descrizione: req.body.descrizione,
        localita: req.body.localita,
        locali: req.body.locali,
        superficie: req.body.superficie,
        camere: req.body.camere,
        bagni: req.body.bagni,
        immagini: immagini,
    }, function (err, updatedImmobile) {
        if (err) return console.error(err);

        res.redirect("/immobili/" + requestedId);
    });
});