【问题标题】:folders and files are not visible after uploading file though multer通过 multer 上传文件后,文件夹和文件不可见
【发布时间】:2021-10-07 18:38:10
【问题描述】:

我正在做一个小项目。一步一步讨论

  1. 起初我通过 multer 上传 zip 文件
  2. 提取这些文件(使用 multer 完成上传后如何调用提取函数?)
  3. 提取这些文件后,我尝试过滤这些文件
  4. 过滤这些文件后,我想将一些文件移动到另一个目录

在我的主要 index.js 我有

  • 上传文件的简单路径正在运行
// MAIN API ENDPOINT 
app.post("/api/zip-upload", upload, async (req, res, next) => {
    console.log("FIles - ", req.files);
});
  • 继续检查是否有需要解压的 zip 文件,但问题是上传后没有显示任何文件或目录
// UNZIP FILES 
const dir = `${__dirname}/uploads`;
const files = fs.readdirSync("./uploads");

const filesUnzip = async () => {
    try {
        if (fs.existsSync(dir)) {
            console.log("files - ", files);
            for (const file of files) {
                console.log("file - ", file);
                try {
                    const extracted = await extract("./uploads/" + file, { dir: __dirname + "/uploads/" });
                    console.log("Extracted - ",extracted);
                    // const directories = await fs.statSync(dir + '/' + file).isDirectory();

                } catch (bufErr) {
                    // console.log("------------");
                    console.log(bufErr.syscall);
                }
            };

            // const directories = await files.filter(function (file) { return fs.statSync(dir + '/' + file).isDirectory(); });
            // console.log(directories);

        }
    } catch (err) {
        console.log(err);
    }
    return;
}


setInterval(() => {
    filesUnzip();
}, 2000);
  • 将文件移动到静态目录,但同样的问题没有找到目录
const getAllDirs = async () => {
    // console.log(fs.existsSync(dir));
    // FIND ALL DIRECTORIES 
    if (fs.existsSync(dir)) {
        const directories = await files.filter(function (file) { return fs.statSync(dir + '/' + file).isDirectory(); });
        console.log("Directories - ",directories);
        if (directories.length > 0) {
            for (let d of directories) {
                const subdirFiles = fs.readdirSync("./uploads/" + d);
                for (let s of subdirFiles) {
                    if (s.toString().match(/\.xml$/gm) || s.toString().match(/\.xml$/gm) !== null) {
                        console.log("-- ", d + "/" + s);

                        const move = await fs.rename("uploads/" + d + "/" + s, __dirname + "/static/" + s, (err) => { console.log(err) });
                        console.log("Move - ", move);
                    }
                }
            }
        }
    }
}
setInterval(getAllDirs, 3000);

【问题讨论】:

    标签: javascript node.js asynchronous multer unzip


    【解决方案1】:

    你的代码有很多问题,我不知道从哪里开始:

    • 如果您的所有函数都是async,为什么还要使用fs.xxxSync() 方法?强烈建议不要使用xxxSync() 方法,因为它会阻塞服务器(即在同步读取过程中不能/不会接受并行请求)。 fs 模块支持promise api ...

    • 您对新文件的“持续检查”始终检查相同的(可能为空)files 数组,因为您似乎只执行了一次files = fs.readdirSync("./uploads");(可能在服务器启动时,但我无法确定,因为该 sn-p 没有任何上下文)

    • 您不应该轮询那个“上传”目录。因为写入文件(如果正确完成)是一个异步过程,您最终可能会读取不完整的文件。相反,您应该从端点处理程序触发解压缩。一旦命中,body.files 将包含已上传的文件。所以你可以简单地使用这个数组来开始任何进一步的处理,而不是频繁地轮询一个目录。

    • 在某些情况下,您使用的是 fs API 的回调版本(例如 fs.rename()。您不能 await 一个需要回调的函数。再次,使用 fs 的 promise api。

    编辑

    所以我正在尝试解决您的问题。也许因为缺少信息,我无法解决所有这些问题,但您应该大致了解一下。

    首先,你应该使用fs 模块的promise api。而且对于路径操作,您应该使用可用的path 模块,该模块将处理一些特定于操作系统的问题。

    const fs = require('fs').promises;
    const path = require('path');
    

    您的 API 端点当前未返回任何内容。我想你剥离了一些代码,但仍然如此。此外,您应该从这里触发文件处理,因此您不必进行目录轮询,即

    1. 容易出错,
    2. 浪费资源和
    3. 如果您像阻塞服务器那样同步执行此操作
    app.post("/api/zip-upload", upload, async (req, res, next) => {
      console.log("FIles - ", req.files);
    
      //if you want to return the result only after the files have been
      //processed use await  
      await handleFiles(req.files);
    
      //if you want to return to the client immediately and process files
      //skip the await
      //handleFiles(req.files);
      res.sendStatus(200);
    });
    

    处理文件似乎包含两个不同的步骤:

    1. 解压上传的 zip 文件
    2. 将一些提取的文件复制到另一个目录中
    const source = path.join(".", "uploads");
    const target = path.join(__dirname, "uploads");
    const statics = path.join(__dirname, "statics");
    
    const handleFiles = async (files) => {
      //a random folder, which will be unique for this upload request
      const tmpfolder = path.join(target, `tmp_${new Date().getTime()}`); 
      
      //create this folder
      await fs.mkdir(tmpfolder, {recursive: true});
    
      //extract all uploaded files to the folder
      //this will wait for a list of promises and resolve once all of them resolved, 
      await Promise.all(files.map(f => extract(path.join(source, f), { dir: tmpfolder })));
    
      await copyFiles(tmpfolder);
    
      //you probably should delete the uploaded zipfiles and the tempfolder 
      //after they have been handled
      await Promise.all(files.map(f => fs.unlink(path.join(source, f))));
      await fs.rmdir(tmpfolder, { recursive: true});
    }
    
    const copyFiles = async (tmpfolder) => {
      //get all files/directory names in the tmpfolder
      const allfiles = await fs.readdir(tmpfolder);
      //get their stats
      const stats = await Promise.all(allfiles.map(f => fs.stat(path.join(tmpfolder, f))));
      //filter directories only
      const dirs = allfiles.filter((_, i) => stats[i].isDirectory());
    
      for (let d of dirs) {
        //read all filenames in the subdirectory
        const files = await fs.readdir(path.join(tmpfolder, d)));
        //filter by extension .xml
        const xml = files.filter(x => path.extname(x) === ".xml");
    
        //move all xml files
        await Promise.all(xml.map(f => fs.rename(path.join(tmpfolder, d, f), path.join(statics, f))));
      }
    }
    

    这应该可以解决问题。当然,您可能会注意到此代码没有错误处理。你应该添加那个。

    而且我不能 100% 确定您的路径。您应该考虑以下事项

    • ./uploads 指的是当前工作目录中的一个目录uploads(无论它在哪里)

    • ${__dirname}/uploads 指的是一个目录uploads,它与当前正在执行的脚本文件在同一目录中不确定这是否是您想要的目录...

    • ./uploads${__dirname}/uploads 可能指向同一个文件夹或完全不同的文件夹。没有额外的上下文是不可能知道的。

    此外,在您的代码中,您将 ZIP 文件从 ./uploads 提取到 ${__dirname}/uploads,然后尝试将 XML 文件从 ./uploads/xxx 复制到 ${__dirname}/statics,但在 @ 中不会有任何目录 xxx 987654346@ 因为您将 ZIP 文件解压缩到(可能)完全不同的文件夹。

    【讨论】:

    • 你能修改我的代码而不是理论上解释吗?因为我对异步js的了解不多。
    猜你喜欢
    • 2019-12-23
    • 2013-09-26
    • 2016-11-24
    • 2016-10-18
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 2018-11-11
    相关资源
    最近更新 更多