Vue|Vue + Node.js 搭建「文件上传」管理后台

本文完整版《Vue + Node.js 搭建「文件上传」管理后台》
本教程手把手带领大家搭建一套通过 Vue + Node.js 上传文件的后台系统,只要你跟随本教程一步步走,一定能很好的理解整个前后端上传文件的代码逻辑。前端我们使用 Vue + Axios + Multipart 来搭建前端上传文件应用,后端我们使用 Node.js + Express + Multer 来搭建后端上传文件处理应用。
当然,本教程还会教给大家如何写一个可以限制上传文件大小、有百分比进度条、可报错、可显示服务器上文件列表、可点击下载文件的前端操作界面。
最后完成的上传文件工具后台如下图,跟随本教学习,你也可以搭出来。
Vue|Vue + Node.js 搭建「文件上传」管理后台
文章图片

如果你对前端不是很熟悉,不想写前端,推荐使用卡拉云搭建后台管理系统,卡拉云是新一代低代码开发工具,不用懂任何前端技术,仅靠鼠标拖拽,即可快速搭建包括「上传文件」在内的任何后台管理工具。立即试用卡拉云 1 分钟搭建「文件上传」工具。详情见本文文末。
Vue + Node.js「上传文件」前后端项目结构 Vue|Vue + Node.js 搭建「文件上传」管理后台
文章图片

Vue 前端部分

  • UploadFilesService.js:这个脚本调用通过 Axios 保存文件和获取文件的方法
  • UploadFiles.vue:这个组件包含所有上传文件相关的信息和操作
  • App.vue:把我们的组件导入到 Vue 起始页
  • index.html:用于导入 Bootstrap
  • http-common.js:配置并初始化 Axios
  • vue.config.js:配置 APP 端口
Node.js 后端部分
  • resources/static/assets/uploads:用于存储上传的文件
  • middleware/upload.js:初始化 Multer 引擎并定义中间件
  • file.controller.js:配置 Rest API
  • routes/index.js:路由,定义前端请求后端如何执行
  • server.js:运行Node.js Express 应用
? 前端部分 - 上传文件 Vue + Axios + Multipart 配置 Vue 环境 使用 npm 安装 Vue 脚手架 vue-cli
npm install -g @vue/cli

Vue|Vue + Node.js 搭建「文件上传」管理后台
文章图片

然后我们创建一个 Vue 项目 kalacloud-vue-multiple-files-upload
vue create kalacloud-vue-multiple-files-upload

安装完成后,cd 进入 kalacloud-vue-multiple-files-upload 目录,接下来所有操作都在这个目录之下。
安装 Axios:
npm install axios

我们先跑一下 Vue ,这是 vue 的默认状态
npm run serve

Vue|Vue + Node.js 搭建「文件上传」管理后台
文章图片

我们可以看到浏览器里 Vue 已经在 localhost:8080 跑起来了。
【Vue|Vue + Node.js 搭建「文件上传」管理后台】扩展阅读:《Vue 搭建带预览的「上传图片」管理后台》
导入 Bootstrap 到项目中 打开 index.html 把以下代码添加到 中:
文件位置:public/index.html
... ...

初始化 Axios HTTP 客户端 在 src 文件夹下,创建 http-common.js 文件,如下所示:
文件位置:src/http-common.js
import axios from "axios"; export default axios.create({ baseURL: "http://localhost:8080", headers: { "Content-type": "application/json" } });

这里的 baseURL 是你上传文件的后端服务器 REST API 地址,请根据实际情况修改。本教程后文,教你搭建上传文件的后端部分,请继续阅读。
创建「上传文件」功能 我们来写一个 JS 脚本,这个脚本调用 Axios 发送 HTTP API 请求,与后端服务器通讯。
这个脚本包含 2 个功能
  • upload(file): POST 数据到后端,再加一个上传进度的回调,可以放个上传进度条。
  • getFiles(): 用于获取服务器上传文件夹中的文件列表
文件位置:src/services/UploadFilesService.js
import http from "../http-common"; class UploadFilesService { upload(file, onUploadProgress) { let formData = https://www.it610.com/article/new FormData(); formData.append("file", file); return http.post("/upload", formData, { headers: { "Content-Type": "multipart/form-data" }, onUploadProgress}); } getFiles() { return http.get("/files"); } } export default new UploadFilesService();

  • 首先导入我们刚刚写好的 Axios HTTP 配置文件 http-common.js
  • FormData 是一种可将数据编译成键值对的数据结构
  • Axios的进度条事件,onUploadProgress 是用来监测上传进度,显示进度信息
  • 最后我们调用 Axios 提供的 post()&get() 来向后端 API 发送 POST & GET 请求
扩展阅读:《Vue Router 手把手教你搭 Vue3 路由》
创建一个 Vue 多文件上传组件 接下来,我们来写一个 Vue 上传组件,这个组件要包含上传文件的所有基本功能,比如 上传按钮、进度条、提示信息、基本 UI 等。
首先,创建一个 Vue 组件模版(UploadFiles.vue)然后把刚刚写好的配置文件(UploadFilesService.js)导入进去。
文件位置:src/components/UploadFiles.vue

然后在这里定义 data() 变量
export default { name: "upload-files", data() { return { selectedFiles: undefined, progressInfos: [], message: "", fileInfos: [], }; }, };

接下来,我们定义 methodsselectFiles()中获取选定的文件。
export default { name: "upload-files", ... methods: { selectFile() { this.progressInfos = []; this.selectedFiles = event.target.files; } } };

selectedFiles 用来访问当前选定的文件,每个文件都有一个对应的进度条(百分比&文件名)以及被 progressInfos 索引。
export default { name: "upload-files", ... methods: { ... uploadFiles() { this.message = ""; for (let i = 0; i < this.selectedFiles.length; i++) { this.upload(i, this.selectedFiles[i]); } } } };

我们通过回调 UploadFilesService.upload() 来获得上传信息
export default { name: "upload-files", ... methods: { ... upload(idx, file) { this.progressInfos[idx] = { percentage: 0, fileName: file.name }; UploadService.upload(file, (event) => { this.progressInfos[idx].percentage = Math.round(100 * event.loaded / event.total); }) .then((response) => { let prevMessage = this.message ? this.message + "\n" : ""; this.message = prevMessage + response.data.message; return UploadService.getFiles(); }) .then((files) => { this.fileInfos = files.data; }) .catch(() => { this.progressInfos[idx].percentage = 0; this.message = "Could not upload the file:" + file.name; }); } } };

  • 文件上传进度我们可以根据event.loadedevent.total 来计算
  • 如果传输完成,我们调用UploadFilesService.getFiles()来获取文件信息,并将结果更新到 fileInfos 里,状态是一个数组 {name, url}
我们还需要在mounted() 中添加调用。
export default { name: "upload-files", ... mounted() { UploadService.getFiles().then((response) => { this.fileInfos = response.data; }); } };

现在我们实现上传文件 UI 的 HTML 模板。将以下内容添加到