前言
近期在做跟毕业筹划相关的数据后台管理系统,此中的列表项展示有图片,添加/编辑功能有文件上传。
“文件上传/删除”也是我们开发中的常见功能,分享个人的实现过程,与各人分享交流
一、预备工作
- 本次案例使用的node版本是18.16.1
- 前端vue2+element-ui
- 后端使用node+express
- 安装对应库:element-ui、axios、multer
留意:本篇重点介绍文件上传的相关功能,后端express的详细使用可以看我的express专栏~
express专栏
二、前端
文件上传组件,来自element-ui组件库
留意:自行安装组件库
Element - The world's most popular Vue UI framework
关于组件,有些展示和功能需要对应设置(比如文件上传的服务器地址,删除后端文件等等)才可以正常使用,以是我对代码进行了修改补充。
1、组件代码
- <template>
- <div>
- <el-upload
- ref="upload"
- action="http://localhost:4000/api/upload" //文件上传的接口
- list-type="picture-card"
- :on-preview="handlePictureCardPreview"
- :on-remove="handleRemove"
- :file-list="fileList"
- :on-change="handleFileChange"
- :on-success="handleUploadSuccess"
- :on-error="handleUploadError"
- name="file"
- >
- <i class="el-icon-plus" />
- </el-upload>
- <el-dialog :visible.sync="dialogVisible">
- <img width="100%" :src="dialogImageUrl" alt="">
- </el-dialog>
- </div>
- </template>
复制代码 2、变量和相关函数
留意:需要安装axios(若安装则跳过)
- <script>
- import Axios from 'axios'
- export default {
- data() {
- return {
- dialogImageUrl: '', //预览时展示的图片
- dialogVisible: false,
- fileList: [] // 用于存储文件列表
- }
- },
- methods: {
- // 生成文件预览 URL
- handleFileChange(file, fileList) {
- file.url = URL.createObjectURL(file.raw)
- this.fileList = fileList
- },
- // 删除文件
- handleRemove(file, fileList) {
- this.fileList = fileList
- // 调用后端删除接口
- if (file.response && file.response.data) {
- this.deleteFile(file.response.data)
- } else {
- this.$message.warning('文件尚未上传成功,无法删除')
- }
- },
- // 预览图片
- handlePictureCardPreview(file) {
- this.dialogImageUrl = file.url
- this.dialogVisible = true
- },
- // 文件上传成功
- handleUploadSuccess(response, file) {
- console.log('文件上传成功', response)
- if (response.code === 0) {
- // 从后端响应中获取图片的 URL
- const imageUrl = response.data
- // 更新 fileList 中的文件 URL
- const index = this.fileList.findIndex(f => f.uid === file.uid)
- if (index !== -1) {
- this.fileList[index].url = imageUrl
- this.fileList[index].response = response // 保存后端返回的响应
- }
- this.$message.success('文件上传成功')
- } else {
- this.$message.error('文件上传失败: ' + response.msg)
- }
- },
- // 文件上传失败
- handleUploadError(err, file) {
- console.error('文件上传失败', err)
- this.$message.error('文件上传失败')
- },
- deleteFile(filename) {
- // 去掉前缀 /public/static/upload/
- const pureFilename = filename.replace('/public/static/upload/', '')
- // 调用后端删除接口
- Axios.delete(`http://localhost:4000/api/upload/${pureFilename}`)
- .then(response => {
- if (response.data.code === 0) {
- this.$message.success('文件删除成功')
- } else {
- this.$message.error('文件删除失败: ' + response.data.msg)
- }
- })
- .catch(err => {
- console.error('文件删除失败', err)
- this.$message.error('文件删除失败')
- })
- }
- }
- }
- </script>
复制代码 3、完整代码
留意看:''localhost:4000''相关字眼(关于后端接口的,下文会作介绍)
- <template>
- <div>
- <el-upload
- ref="upload"
- action="http://localhost:4000/api/upload"
- list-type="picture-card"
- :on-preview="handlePictureCardPreview"
- :on-remove="handleRemove"
- :file-list="fileList"
- :on-change="handleFileChange"
- :on-success="handleUploadSuccess"
- :on-error="handleUploadError"
- name="file"
- >
- <i class="el-icon-plus" />
- </el-upload>
- <el-dialog :visible.sync="dialogVisible">
- <img width="100%" :src="dialogImageUrl" alt="">
- </el-dialog>
- </div>
- </template>
- <script>
- import Axios from 'axios'
- export default {
- data() {
- return {
- dialogImageUrl: '',
- dialogVisible: false,
- fileList: [] // 用于存储文件列表
- }
- },
- methods: {
- // 生成文件预览 URL
- handleFileChange(file, fileList) {
- file.url = URL.createObjectURL(file.raw)
- this.fileList = fileList
- },
- // 删除文件
- handleRemove(file, fileList) {
- this.fileList = fileList
- // 调用后端删除接口
- if (file.response && file.response.data) {
- this.deleteFile(file.response.data)
- } else {
- this.$message.warning('文件尚未上传成功,无法删除')
- }
- },
- // 预览图片
- handlePictureCardPreview(file) {
- this.dialogImageUrl = file.url
- this.dialogVisible = true
- },
- // 文件上传成功
- handleUploadSuccess(response, file) {
- console.log('文件上传成功', response)
- if (response.code === 0) {
- // 从后端响应中获取图片的 URL
- const imageUrl = response.data
- // 更新 fileList 中的文件 URL
- const index = this.fileList.findIndex(f => f.uid === file.uid)
- if (index !== -1) {
- this.fileList[index].url = imageUrl
- this.fileList[index].response = response // 保存后端返回的响应
- }
- this.$message.success('文件上传成功')
- } else {
- this.$message.error('文件上传失败: ' + response.msg)
- }
- },
- // 文件上传失败
- handleUploadError(err, file) {
- console.error('文件上传失败', err)
- this.$message.error('文件上传失败')
- },
- // 删除后端文件,参数传递的是文件名(经前端上传过后,返回给前端的文件名)
- deleteFile(filename) {
- // 去掉前缀 /public/static/upload/
- const pureFilename = filename.replace('/public/static/upload/', '')
- // 调用后端删除接口
- Axios.delete(`http://localhost:4000/api/upload/${pureFilename}`)
- .then(response => {
- if (response.data.code === 0) {
- this.$message.success('文件删除成功')
- } else {
- this.$message.error('文件删除失败: ' + response.data.msg)
- }
- })
- .catch(err => {
- console.error('文件删除失败', err)
- this.$message.error('文件删除失败')
- })
- }
- }
- }
- </script>
- <style>
- .el-upload-list__item-thumbnail {
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
- </style>
复制代码 三、后端
1、搭建express应用
【express-generator】01-安装和基本使用
如果按照文章步骤(默认端口是3000,我这里设置成4000端口),则对应更换端口为4000,在创建的express项目标bin/www中进行修改。
2、新建文件夹及文件
2.1、新建public/static/upload
这是存储上传文件的位置。
2.2、新建routes/upload.js,撰写路由方法。
安装multer,这是处理文件上传的相关库。
npm install multer

- var express = require("express");
- const multer = require("multer");
- const { uploading } = require("../utils/tool");
- const fs = require('fs');
- const path = require('path');
- var router = express.Router();
- // 文件上传接口
- router.post("/", async function (req, res, next) {
- // single 方法里面书写上传控件的 name 值
- uploading.single("file")(req, res, function (err) {
- if (err instanceof multer.MulterError) {
- next("上传文件失败,请检查文件的大小,控制在 6MB 以内");
- } else {
- console.log("req.file>>>", req.file);
-
- const filePath = "/public/static/upload/" + req.file.filename;
- res.send({ code: 0, msg: "文件上传成功", data: filePath });
- }
- })
- });
- // 文件删除接口
- router.delete("/:filename", function (req, res, next) {
- const filename = req.params.filename;
- const filePath = path.join(__dirname, '../public/static/upload',filename);
- console.log("后端接收到的文件参数>>>",filename,"完整基本路径是>>>>",filePath);
- fs.unlink(filePath, (err) => {
- if (err) {
- console.error("删除文件失败", err);
- return res.status(500).send({ code: 1, msg: "删除文件失败" });
- }
- res.send({ code: 0, msg: "文件删除成功" });
- });
- });
- module.exports = router;
复制代码 2.3、新增utlis/tool.js,撰写工具类函数。
- const multer = require("multer");
- const path = require("path");
- // 设置上传文件的引擎
- const storage = multer.diskStorage({
- // 文件存储的位置
- destination: function (req, file, cb) {
- cb(null, __dirname + '/../public/static/upload');
- },
- // 上传到服务器的文件,文件名要做单独处理
- filename: function (req, file, cb) {
- // 获取文件名
- const basename = path.basename(file.originalname, path.extname(file.originalname));
- // 获取后缀名
- const extname = path.extname(file.originalname);
- // 构建新的名字
- const newName = basename + new Date().getTime() + Math.floor(Math.random() * 9000 + 1000) + extname;
- cb(null, newName);
- }
- })
- module.exports.uploading = multer({
- storage: storage,
- limits: {
- fileSize: 6000000,
- files: 1
- }
- })
复制代码 3、在app.js中引入和使用
- var createError = require('http-errors');
- var express = require('express');
- var path = require('path');
- var cookieParser = require('cookie-parser');
- var logger = require('morgan');
- const cors = require('cors');
- // 文件上传
- const multer = require('multer');
- const fs = require('fs');
- // const path = require('path');
- var indexRouter = require('./routes/index');
- var usersRouter = require('./routes/users');
- var uploadRouter = require('./routes/upload');
- var app = express();
- // view engine setup
- app.set('views', path.join(__dirname, 'views'));
- app.set('view engine', 'jade');
- // 允许所有来源访问
- app.use(cors());
- // 文件上传
- // const upload = multer({ dest: 'static/upload/' });
- app.use(express.static(path.join(__dirname, 'public')));
- app.use(logger('dev'));
- app.use(express.json());
- app.use(express.urlencoded({ extended: false }));
- app.use(cookieParser());
- app.use(express.static(path.join(__dirname, 'public')));
- app.use('/', indexRouter);
- app.use('/users', usersRouter);
- app.use('/api/upload/', uploadRouter);
- // error handler
- app.use(function(err, req, res, next) {
- // set locals, only providing error in development
- res.locals.message = err.message;
- res.locals.error = req.app.get('env') === 'development' ? err : {};
- // render the error page
- res.status(err.status || 500);
-
- res.render('error');
- });
- module.exports = app;
复制代码 四、测试
1、上传文件(图片)
查看存储上传文件的位置
2、删除文件(图片)
前端组件,鼠标进入到图片区域,点击删除按键
前端作出对应提示
末了前端的文件列表也为空,成功删除了文件。
后端查看文件夹,发现刚上传的文件由于前端的删除操作,也对应进行了删除。
五、总结
一些留意点
express应用默认端口号是3000,而案例演示的是4000(因为一般环境,3000端口容易被其他代码程序给使用用,制止这种环境,可以使用一个新的端口号(或者把占用3000端口的程序都关闭))
关于文件上传的设置,涉及到的知识点比力多,比如fs.unlink,path相关的知识,需要各人自行进行补充了解,部门知识点可以参考下方这篇博客文章。
【NODE】01-fs和path常用知识点
如果有问题,请留言评论~
如果你喜欢这篇文章,留下你的点赞和收藏~
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |