【问题标题】:Delete Previous Files in Directory, Create New Files and Download Newly Created Files With Nodejs删除目录中以前的文件,创建新文件并使用 Nodejs 下载新创建的文件
【发布时间】:2021-12-07 04:38:59
【问题描述】:

我正在创建一个简单的节点应用程序。我想要达到的目标:

我的应用程序将网页链接和一些关键字作为输入。现在我想根据输入的关键字创建新的网页。所以如果我进入优秀的程序员,优秀的问题解决者,nodejs 开发者。它应该创建 3 个新文件 good_programmer.php、great_problem_solver.php。 nodejs_developer.php 然后我想下载这些文件。

我对这个问题的建议解决方案如下:

    const fs = require("fs");
const path = require("path");
const axios = require("axios");
const cheerio = require("cheerio");
const zipadm = require("adm-zip");
const zip = new zipadm();
// initialize app
const app = express();
// to handle the forms
app.use(express.urlencoded({ extended: false }))
// initialize port
const PORT = 8000;
// util functions
function deletePreviousFiles() {
    return new Promise((res, rej) => {
        fs.readdir(__dirname, (err, files) => {
            if (err) throw err;
            for (const file of files) {
                if (file.includes(".php") || file.includes("sitemap.txt") || file.includes(".zip")) {
                    fs.unlink(path.join(__dirname, file), err => {
                        if (err) throw err;
                    });
                }
            }
            res();
        })
    })
}
function generateSitemapFile(webpage, words) {
    return new Promise((res, rej) => {
        let keywords = words.split(",");
        for (let i = 0; i < keywords.length; i++) {
            let fileName = keywords[i].trim().replace(" ", "_");
            let newLink = `${webpage}${fileName}.php`;
            fs.appendFile(`sitemap.txt`, `${newLink}\n`, function (err) {
                if (err) throw err;
            });
        }
        res();
    })
}
function generatePHPFiles(data, words) {
    return new Promise((res, rej) => {
        const $ = data;
        $.html();
        let keywords = words.split(",");
        for (let i = 0; i < keywords.length; i++) {
            let fileName = keywords[i].trim().replace(" ", "_");
            fs.writeFile(`${fileName}.php`, $.html(), (err) => {
                if (err) throw err;
            })
        }
        res();
    })
}
function createZipFile() {
    return new Promise((res, rej) => {
        fs.readdir(__dirname, (err, files) => {
            if (err) throw err;
            for (const file of files) {
                if (file.includes(".php") || file.includes("sitemap.txt")) {
                    zip.addFile(file);
                    data = zip.toBuffer();
                    zip.writeZip("NewPhpFiles.zip");
                }
            }
            res();
        })
    })
}
// controller
const startApplication = async (req, res, next) => {
    try {
        const webPageLink = req.body.link;
        const seoKeywords = req.body.keywords;        
        // delete previous files on desk
        await deletePreviousFiles();
        console.log("Previous Files Deleted...");
        // generate sitemap.txt file
        await generateSitemapFile(webPageLink, seoKeywords);
        console.log("Sitemap Created...");
        // get web page response
        let response = await axios.get(webPageLink);
        const data = await cheerio.load(response.data);
        console.log("Data Loaded From Page...")
        // create new php files
        generatePHPFiles(data, seoKeywords);
        console.log("PHP Files Created...")
        // create a zip file
        createZipFile();
        console.log("ZIP Created...")     
        next();
    } catch (error) {
        console.log(error)
    }
}
const downloadFile = async (req,res) => {
    try {
        setTimeout(()=>{
            res.download("NewPhpFiles.zip");
        },1000)
    } catch (error) {
        console.log(error)
    }
}
app.use(startApplication)
// initialize the route for application
app.post("/submit", downloadFile)
// start app
app.listen(PORT, console.log(`App is listening on port: ${PORT}...`)); 

所以,我正在删除磁盘上现有的 php 文件,然后创建新文件并压缩它们,但它不会下载新文件。似乎创建新文件需要很长时间。

【问题讨论】:

    标签: javascript node.js async-await promise settimeout


    【解决方案1】:

    我认为您并不完全了解 js 的工作原理。让我们从那开始。例如,让我们使用 deletePreviousFiles 函数。 fs.readdir 和 fs.unlink 具有回调,您需要等待这些回调,以确保在执行函数时完成您想做的所有事情。在 deletePreviousFiles 函数中,您正在等待 fs.readdir 而不是 fs.unlink。也没有正确处理错误。有多种方法可以解决这个问题。当然,您可以使用 callbaks 来做到这一点,但有更简单的解决方案。您可以使用 fs 包提供的同步功能。或者您可以使用 async/await 来避免回调混乱。我强烈建议使用 fs/promise 包。

    让我们对你的函数进行重构。

    async function deletePreviousFiles() {
        let files = await fs.promises.readdir(__dirname);
        for (const file of files) {
            if (file.includes(".php") || file.includes("sitemap.txt") || file.includes(".zip")) {
                await fs.promises.unlink(path.join(__dirname, file))
            }
        }
    }
    

    这样当你调用 deletePreviousFiles 函数时,你会确定你想做的一切都完成了。 (别忘了这个函数是一个异步函数并返回一个promise。所以你需要处理它。基本上用await调用)

    在 downloadFile 函数中有一个超时函数。我假设您这样做是为了等待必要的操作。这是错误的做法。对于此类操作,您无法估计需要多长时间。你需要确保它已经完成。不要使用 timeout 来等待 io 操作!

    同样在 startApplication 函数中,您使用 await 调用了一些异步函数,而其他一些您没有调用。例如,您在没有等待的情况下调用了 generatePHPFiles。因此,通过该行后,您将在控制台上打印文件已创建但实际上并未创建。

    我认为你需要先了解回调和 asyc/await 如何在 js 中工作。如果您有更多问题,请随时提问。祝你有美好的一天:)

    【讨论】:

    • 是的,我并不完全了解 JS 的工作原理,我需要了解回调和 aync/await 在 JS 中的工作原理。但是应用这个之后,它仍然没有下载文件。
    • 是的,我没有修复所有错误。仅作为示例更正了一个功能。正如我提到的,还有其他问题需要解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-04
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    相关资源
    最近更新 更多