如何使用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('服务器已启动');
});
相关推荐
燃先生._.1 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖2 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235242 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240253 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar3 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人3 小时前
前端知识补充—CSS
前端·css
GISer_Jing4 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_748245524 小时前
吉利前端、AI面试
前端·面试·职场和发展
理想不理想v4 小时前
webpack最基础的配置
前端·webpack·node.js