如何使用Node在指定文件夹实现文件的上传与删除?

目标:

在上一篇文章中,我们简单介绍了如何使用nginx对页面及文件夹进行代理,我们本篇来简单介绍一下,前端如何使用node定义一个上传接口,并上传和删除文件。

环境

我们本篇采取的是使用node进行文件管理,所以,node环境就是不可缺少的了,那我们安装完了node,还需要准备什么呢?

node作为一个V8引擎的JavaScript运行环境,可以在服务器端运行JavaScript代码,并且已经广泛应用于Web服务器、实时通信应用、微服务架构、大数据处理等领域,已经成为前端开发人员必备的技能之一。它采用事件驱动非阻塞I/O模型,使得可以处理大量并发连接而不会导致阻塞,适用于构建高性能、可扩展的网络应用,它提供了大量的模块,例如:fshttppatheventsutiloscryptostreamchild_processexpress等等。这里我们只罗列了一些ndoe常用的模块,但是绝对不仅仅是这些,可千万不要小瞧了它,今天我们就用node来实现一个文件的管理。

express

express是一个流行的Node.js Web应用框架,它简化了构建Web应用程序的过程。它提供了一组简洁灵活的API,使开发者能够轻松地处理HTTP请求、路由、中间件等。以下是一些express框架的主要特点和功能:

  • 简洁而灵活express提供了一组简洁而灵活的API,使得开发者能够快速构建Web应用程序。它遵循"最小化即最佳化"的设计原则,只提供了核心的功能,而其他高级功能则可以通过中间件和插件进行扩展。
  • 路由处理express提供了灵活的路由处理机制,可以根据不同的URL路径和HTTP方法来匹配和处理请求。通过定义不同的路由,可以将请求分发到相应的处理函数,并实现不同URL路径的路由映射。
  • 中间件express支持使用中间件来处理请求和响应。中间件是一个函数,可以在请求到达路由处理函数之前或之后进行一些操作,如身份验证、日志记录、错误处理等。中间件可以串联使用,形成一个处理请求的管道。
  • 模板引擎express支持使用各种模板引擎来生成动态的HTML页面。可以使用ejspughandlebars等模板引擎来渲染页面,并将动态数据插入到模板中。
  • 静态文件服务express可以轻松地提供静态文件服务,如图片、CSS、JavaScript等。通过使用express.static中间件,可以指定一个目录,将其中的静态文件直接提供给客户端。
  • 错误处理express提供了一套错误处理机制,可以捕获和处理请求处理过程中的错误。可以通过定义错误处理中间件来统一处理错误,并返回适当的错误响应。
  • 扩展性express是一个非常灵活的框架,可以通过使用第三方中间件和插件来扩展其功能。有许多第三方中间件可供选择,如body-parsercookie-parserpassport等,可以用于处理请求体解析、Cookie解析、用户认证等。

multer

multer是一个Node.js的中间件模块,用于处理HTTP请求中的文件上传。它基于busboy库实现,可以方便地处理表单中的文件上传操作。以下是multer模块的主要特点和功能:

  • 文件上传multer提供了方便的API来处理文件上传操作。它可以处理单个文件上传、多个文件上传,以及混合文件和其他数据的表单上传。
  • 配置选项multer提供了一些配置选项,可以根据需求进行定制。可以设置文件上传的最大大小、文件类型限制、保存路径等。
  • 中间件multer可以作为一个中间件函数在Express等Web框架中使用。通过将multer中间件插入到路由处理函数之前,可以在请求到达路由处理函数之前对上传的文件进行处理。
  • 文件信息multer通过req.file属性提供了上传文件的信息。可以访问文件的原始名称、保存名称、大小、MIME类型等。
  • 多存储引擎支持multer支持多种存储引擎,可以将上传的文件保存到不同的位置,如本地文件系统、内存、云存储等。可以根据需求选择适合的存储引擎。

path

path是一个Node.js内置模块,用于处理文件路径和目录路径。它提供了一组方法,可以方便地处理和操作文件路径的字符串。以下是path模块的主要方法和功能:

  • 路径拼接path.join()方法可以将多个路径片段拼接成一个完整的路径。它会根据操作系统的规范自动处理斜杠和反斜杠的差异。
  • 路径解析path.parse()方法可以解析一个路径字符串,并返回一个包含路径各个部分的对象。可以通过该对象访问路径的根目录、目录名、文件名、扩展名等信息。
  • 路径规范化path.normalize()方法可以将一个路径字符串规范化,消除冗余的斜杠和点。它会处理路径中的相对路径和上级目录,返回一个规范化后的路径。
  • 路径相对化path.relative()方法可以根据当前工作目录计算出两个路径之间的相对路径。它会返回一个相对于第一个路径的相对路径。
  • 路径解析和拼接path.resolve()方法可以将多个路径解析为一个绝对路径。它会根据当前工作目录解析相对路径,并处理上级目录和根目录。
  • 路径分隔符path.sep属性是当前操作系统的路径分隔符。在Windows上为反斜杠``,在POSIX系统上为斜杠/
  • 文件扩展名path.extname()方法可以返回一个路径的文件扩展名。它会提取路径中最后一个点后面的部分作为扩展名。

单/多文件上传

其实我们在node连接数据库并进行查询,编辑(点击跳转)这篇文章中已经提过荣誉和进行接口的定义,使用的同样也是express,因此我们可以借鉴上一篇文章的借口定义,只不过,我们之前调取接口时候,采用的是query拼接,或者是通过body传参一个对象到服务端,而作为文件上传,我们同样采用的是post格式的body传参,只不过这里body里面的传参,并不是单纯的对象,而是字段的keyfilevalueformData的格式的对象。

在上面,我们也介绍了这次用到的几个模块分别是做什么的,下面我们就直接上代码:

js 复制代码
const express = require('express');
const multer = require('multer');
const path = require('path');

const app = express();

const storage = multer.diskStorage({
    // 因为我需要上传到上一篇建立的nginx的代理文件夹下,所以不能使用相对路径
    // 使用path.join()来把路径直接拼接起来
    destination: path.join('/Users/wangtianxiang/Desktop/fileServe/', 'upload/'),
    filename: (req, file, cb) => {
        const ext = path.extname(file.originalname);
        const fileName = file.originalname.replace(ext, '');
        cb(null, fileName + ext); // 拼接文件名+后缀
    }
});
// multer在保存上传的文件时,默认情况下不会保留文件的后缀名,14行拼接的原因
const upload = multer({ storage });

app.post('/file/upload', upload.single('file'), (req, res) => {
    // req.file 是上传的文件信息
    res.send('文件上传成功');
});

app.listen(3000, () => {
    console.log('服务器已启动');
});

到这里,一个简单的上传的服务就写好了,我们只需要启动这个服务就可以了,接下来我们来试试能不能达到我们预期的效果:

可以看到,我们现在单个文件上传已经可以实现了,并能够在指定文件夹中访问到,但是我们多文件上传的时候,会报错如下,因为目前还没有进行多文件上传的配置

这时候,我们需要将upload.single替换成upload.array,第一个参数依旧是file,第二个参数为多文件上传数量限制,完整代码如下:

js 复制代码
const express = require('express');
const multer = require('multer');
const path = require('path');

const app = express();

const storage = multer.diskStorage({
    destination: path.join('/Users/wangtianxiang/Desktop/fileServe/', 'upload/'),
    filename: (req, file, cb) => {
        const ext = path.extname(file.originalname);
        const fileName = file.originalname.replace(ext, '');
        cb(null, fileName + ext); // 拼接文件名+后缀
    }
});
const upload = multer({ storage });

app.post('/file/upload', upload.array('file', 5), (req, res) => {
    // req.files 是上传的文件信息的数组
    res.send('文件上传成功');
});

app.listen(3000, () => {
    console.log('服务器已启动');
});

我们来看一下,是否达到了预期的效果:

可以看到,我们多选的额文件,都是成功了的,到这里,文件上传也就告一段落了。

文件删除

说到文件删除,我们就必须要用到fs模块了,fs 模块是Node.js的文件系统模块,用于对文件系统进行操作。它提供了一系列的方法,用于读取、写入、删除、重命名等文件系统操作。下面我们直接上代码:

js 复制代码
const fs = require('fs');
const path = require('path');
const express = require('express');

const app = express();
const folderPath = path.join('/Users/wangtianxiang/Desktop/fileServe/', 'upload/');

app.delete('/file/delete', (req, res) => {
    console.log(req)
    fs.readdir(folderPath, (err, files) => {
        if (err) return res.status(500).send('读取文件夹失败');
        files.forEach((file) => {
            if (file === req.query.filename) {
                const filePath = path.join(folderPath, file);
                fs.unlink(filePath, (err) => {
                    if (err) return (res.send(`删除文件失败:${err}`))
                    res.send(`文件 ${file} 删除成功`);
                });
            }

        });
    });
});

app.listen(3000, () => {
    console.log('服务器已启动');
});

在这和段代码中,我们从指定文件夹中,删除了指定文件名的文件,下面我们通过apiFox进行接口调用:

在这个文件夹下,我们有三个文件,我们删除snake.html如下图:

可以看到,我们已经从文件夹中,将snake.html文件删除成功。至于对文件删除,经过最近三篇文章,大家应该也知道怎么删除了,同样的逻辑,只不过我们可以换成post请求方式,传入一个数组,从req中获取,循环传入需要删除的数组,调用fs.unlink进行删除即可。

至此,文件的上传,查看,删除就都完成了,如果需要将文件管理做成一个界面版的,需要结合最近三篇文章,这样我们就可以在浏览器中,对文件夹文件进行管理了。

完整代码

js 复制代码
const express = require('express');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

const app = express();
const folderPath = path.join('/Users/wangtianxiang/Desktop/fileServe/', 'upload/');

const storage = multer.diskStorage({
    destination: folderPath,
    filename: (req, file, cb) => {
        const ext = path.extname(file.originalname);
        const fileName = file.originalname.replace(ext, '');
        cb(null, fileName + ext); // 拼接文件名+后缀
    }
});
const upload = multer({ storage });

app.post('/file/upload', upload.array('file', 5), (req, res) => {
    // req.files 是上传的文件信息的数组
    res.send('文件上传成功');
});

app.delete('/file/delete', (req, res) => {
    console.log(req)
    fs.readdir(folderPath, (err, files) => {
        if (err) return res.status(500).send('读取文件夹失败');
        files.forEach((file) => {
            if (file === req.query.filename) {
                const filePath = path.join(folderPath, file);
                fs.unlink(filePath, (err) => {
                    if (err) return (res.send(`删除文件失败:${err}`))
                    res.send(`文件 ${file} 删除成功`);
                });
            }

        });
    });
});

app.listen(3000, () => {
    console.log('服务器已启动');
});
相关推荐
腾讯TNTWeb前端团队13 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom5 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom5 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom5 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom5 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试