乐趣区

关于vue.js:Vue-Nodejs-搭建文件上传管理后台

本文完整版《Vue + Node.js 搭建「文件上传」治理后盾》

本教程手把手率领大家搭建一套通过 Vue + Node.js 上传文件的后盾零碎,只有你追随本教程一步步走,肯定能很好的了解整个前后端上传文件的代码逻辑。前端咱们应用 Vue + Axios + Multipart 来搭建前端上传文件利用,后端咱们应用 Node.js + Express + Multer 来搭建后端上传文件解决利用。

当然,本教程还会教给大家如何写一个能够限度上传文件大小、有百分比进度条、可报错、可显示服务器上文件列表、可点击下载文件的前端操作界面。

最初实现的上传文件工具后盾如下图,追随本教学习,你也能够搭进去。

如果你对前端不是很相熟,不想写前端,举荐应用卡拉云搭建后盾管理系统,卡拉云是新一代低代码开发工具,不必懂任何前端技术,仅靠鼠标拖拽,即可疾速搭建包含「上传文件」在内的任何后盾管理工具。立刻试用卡拉云 1 分钟搭建「文件上传」工具。详情见本文文末。

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 我的项目 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 曾经在 localhost:8080 跑起来了。

扩大浏览:《Vue 搭建带预览的「上传图片」治理后盾》

导入 Bootstrap 到我的项目中

关上 index.html 把以下代码增加到<head> 中:

文件地位:public/index.html

<!DOCTYPE html>
<html lang="en"><head>
...
<link type="text/css" rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" />
</head>
  ...
</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 = 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

<template>
</template>
<script>
import UploadService from "../services/UploadFilesService";
export default {
  name: "upload-files",
  data() {return {};
  },
  methods: {}};
</script>

而后在这里定义 data() 变量

export default {
  name: "upload-files",
  data() {
    return {
      selectedFiles: undefined,
      progressInfos: [],
      message: "",
      fileInfos: [],};
  },
};

接下来,咱们定义 methods 让 selectFiles() 从 <input type="file" >中获取选定的文件。

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 模板。将以下内容增加到<template>

<template>
  <div>
    <div v-if="progressInfos">
      <div class="mb-2"
        v-for="(progressInfo, index) in progressInfos"
        :key="index"
      >
        <span>{{progressInfo.fileName}}</span>
        <div class="progress">
          <div class="progress-bar progress-bar-info"
            role="progressbar"
            :aria-valuenow="progressInfo.percentage"
            aria-valuemin="0"
            aria-valuemax="100"
            :style="{width: progressInfo.percentage +'%'}"
          >
            {{progressInfo.percentage}}%
          </div>
        </div>
      </div>
    </div>
    <label class="btn btn-default">
      <input type="file" multiple @change="selectFile" />
    </label>
    <button class="btn btn-success"
      :disabled="!selectedFiles"
      @click="uploadFiles"
    >
      上传
    </button>
    <div v-if="message" class="alert alert-light" role="alert">
      <ul>
        <li v-for="(ms, i) in message.split('\n')" :key="i">
          {{ms}}
        </li>
      </ul>
    </div>
    <div class="card">
      <div class="card-header"> 文件列表 </div>
      <ul class="list-group list-group-flush">
        <li class="list-group-item"
          v-for="(file, index) in fileInfos"
          :key="index"
        >
          <a :href="file.url">{{file.name}}</a>
        </li>
      </ul>
    </div>
  </div>
</template>

在下面的代码中,咱们应用 Bootstrap 进度条,这里不开展讲了,更多细节可查看 Bootstrap 文档。

在 App.vue 中增加「文件上传」组件

关上 App.vue , 在代码中导入 UploadFiles 组件。

<template>
  <div id="app">
    <div class="container" style="width:600px">
      <div style="margin: 20px">
<h2> 应用 Vue 搭建文件上传 Demo</h2>
        <h5><a href="http://kalacloud.com"> 卡拉云 </a> - 低代码开发工具,1 秒搭建上传后盾 </h5>
                <a> 应用卡拉云无需懂任何前端技术,仅需拖拽即可搭建属于你的后盾管理系统 </a>

      </div>
      <upload-files></upload-files>
    </div>
  </div>
</template>
<script>
import UploadFiles from "./components/UploadFiles";
export default {
  name: "App",
  components: {UploadFiles}
};
</script>

给 Vue 上传文件服务配置拜访端口

文件地位:src/vue.config.js

module.exports = {
  devServer: {port: 8081}
}

运行 Vue 前端局部

到这里,咱们曾经把 Vue 上传文件的前端局部写完,运行起来看看成果吧。

在 kalacloud-vue-multiple-files-upload 根目录跑一下:

npm run serve

在浏览器关上 http://localhost:8081/ 能够看到前端局部曾经完满显示。

文件选择器、上传按钮、文件列表都曾经能够显示进去了,但还无奈上传。这是因为后端局部还没有跑起来,接下来,我率领大家手把手搭建上传文件的后端局部。

扩大浏览:《5 款最棒的 Vue UI 挪动端组件库 – 特地针对国内应用场景举荐》

Vue 前端「上传文件」源码

你能够在我的 github 上下载到残缺的 Vue 上传文件 Demo。

当然你也能够不必这么吃力搭建前端做上传文件性能,间接应用卡拉云,无需懂前后端,简略拖拽即可生成一套属于你本人的后盾管理工具。

✦ 后端局部 – 上传文件 Node.js + Express + Multer

前文咱们介绍了如何应用 Vue 搭建上传文件管理工具的前端局部,接下来我教大家应用 Node.js + Express + Multer 来搭建一套上传文件的后端 Rest API,提供给 Vue 前端应用,从而实现 Vue 抉择文件 + Axios 调用后端 API HTTP 通信,最初把文件上传到服务器指定目录。

接下来,大家一起追随本教程创立一套 Node.js 上传文件 Rest API,它的性能包含:

  • 将 Vue 前端选中的文件上传到服务器的动态文件夹中
  • 限度上传文件大小,最大 2MB
  • GET 服务器中存储文件的 URL,可用于下载
  • GET 文件信息列表(文件名 + URL)

这是存储所有上传文件的动态文件夹:

如果咱们 GET 文件列表,Node.js Rest API 会返回:

GET /files,API 返回 文件名 + URL

咱们构建的 Node.js Rest API 蕴含这三个性能:

  • POST /upload 上传一个文件
  • GET /files 获取文件列表(文件名 +URL)
  • GET /files/[filename] 下载指定文件

扩大浏览:《顶级好用的 5 款 Vue table 表格组件测评与举荐》

配置 Node.js 开发环境

在根目录新建 Node.js 的后端文件夹 kalacloud-express-file-upload,接下来所有操作都在这个文件夹中进行。

mkdir kalacloud-express-file-upload
cd kalacloud-express-file-upload

在 kalacloud-express-file-upload 文件夹根目录装置 Express、Multer、CORS 这三个模块:

npm install express multer cors

package.json 文件:

{
  "name": "kalacloud-express-file-upload",
  "version": "1.0.0",
  "description": "Node.js Express Rest APis to Upload/Download Files",
  "main": "server.js",
  "scripts": {"test": "echo \"Error: no test specified\"&& exit 1"},
  "keywords": [
    "node js",
    "upload",
    "download",
    "file",
    "multipart",
    "rest api",
    "express"
  ],
  "author": "bezkoder",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "multer": "^1.4.2"
  }
}

配置文件上传中间件 Multer

咱们应用 Multer 中间件来解决多文件上传,更多 Multer 细节请浏览它的开发文档

文件地位:src/middleware/upload.js

const util = require("util");
const multer = require("multer");
const maxSize = 2 * 1024 * 1024;
let storage = multer.diskStorage({destination: (req, file, cb) => {cb(null, __basedir + "/resources/static/assets/uploads/");
  },
  filename: (req, file, cb) => {console.log(file.originalname);
    cb(null, file.originalname);
  },
});
let uploadFile = multer({
  storage: storage,
  limits: {fileSize: maxSize},
}).single("file");
let uploadFileMiddleware = util.promisify(uploadFile);
module.exports = uploadFileMiddleware;

下面的代码咱们做了这么几件事:

  • 导入 multer 模块。
  • 配置 multer 为磁盘存储引擎。
  • destination:指向用于存储上传文件的文件夹。
  • filename:上传文件上传后的文件名。

扩大浏览:《最好用的 7 款 Vue admin 后盾治理框架测评》

应用 Multer 限度文件大小

咱们能够应用 Multer API 来限度上传文件大小,增加 limits: {fileSize: maxSize} 以限度文件大小。

let storage = multer.diskStorage(...);
const maxSize = 2 * 1024 * 1024;
let uploadFile = multer({
  storage: storage,
  limits: {fileSize: maxSize}
}).single("file");

创立文件上传 / 下载控制器

在 controller 文件夹中创立 file.controller.js

上传文件:咱们应用 upload() 函数

  • 应用中间件性能上传文件
  • 上传文件错误信息(在 Multer 中间件函数中)
  • 返回信息

下载文件:

  • 应用 getListFiles() 读取服务器上传文件夹中的所有文件,蕴含文件名和 URL
  • 应用 download() 接管文件名作为输出参数,而后应用 Express res.downloa() 以附件模式传输 URL(目录 + 文件名)

文件地位:src/controller/file.controller.js

const uploadFile = require("../middleware/upload");
const upload = async (req, res) => {
  try {await uploadFile(req, res);
    if (req.file == undefined) {return res.status(400).send({message: "请抉择要上传的文件"});
    }
    res.status(200).send({message: "文件上传胜利:" + req.file.originalname,});
  } catch (err) {res.status(500).send({message: ` 无奈上传文件: ${req.file.originalname}. ${err}`,
    });
  }
};
const getListFiles = (req, res) => {
  const directoryPath = __basedir + "/resources/static/assets/uploads/";
  fs.readdir(directoryPath, function (err, files) {if (err) {res.status(500).send({message: "没有找到文件。",});
    }
    let fileInfos = [];
    files.forEach((file) => {
      fileInfos.push({
        name: file,
        url: baseUrl + file,
      });
    });
    res.status(200).send(fileInfos);
  });
};
const download = (req, res) => {
  const fileName = req.params.name;
  const directoryPath = __basedir + "/resources/static/assets/uploads/";
  res.download(directoryPath + fileName, fileName, (err) => {if (err) {res.status(500).send({message: "无奈获取文件。" + err,});
    }
  });
};
module.exports = {
  upload,
  getListFiles,
  download,
};
  • 咱们首先调用中间件函数 uploadFile()
  • 如果 HTTP 申请不蕴含文件,返回 400 错误信息
  • 如果呈现获取谬误,返回 500 错误信息

如果用户上传文件大小超限的文件应该怎么解决?

扩大浏览:《手把手教你 Vue3+Node.js+Expres+MySQL 环境搭建》

应用 Multer 解决文件大小超限谬误

咱们能够通过 catch() 来查看文件超限谬误(LIMIT_FILE_SIZE

文件地位:src/controller/file.controller.js

 const upload = async (req, res) => {
  try {await uploadFile(req, res);
    ...
  } catch (err) {if (err.code == "LIMIT_FILE_SIZE") {return res.status(500).send({message: "文件大小不能超过 2MB",});
    }
    res.status(500).send({message: ` 不能上传文件: ${req.file.originalname}. ${err}`,
    });
  }
};

设置后端 Rest API 上传文件的门路

当 Vue 前端通过 Axios 发送 HTTP 申请时,咱们须要通过路由来确定服务器应该如何响应

咱们来设置三种罕用到的上传文件所需性能

  • POST /uploadupload()
  • GET /filesgetListFiles()
  • GET /files/[fileName]download()

咱们在 routes 文件夹中创立 index.js 文件:

文件地位:src/routes/index.js

const express = require("express");
const router = express.Router();
const controller = require("../controller/file.controller");
let routes = (app) => {router.post("/upload", controller.upload);
  router.get("/files", controller.getListFiles);
  router.get("/files/:name", controller.download);
  app.use(router);
};
module.exports = routes;

下面这段代码调用了咱们前文写的控制器 file.controller.js

扩大浏览:《最好的 5 款翻译 API 接口比照测评》

创立 Express 服务

最初一步,创立 Express 服务,在根目录新建一个 server.js 文件

文件地位:kalacloud-express-file-upload/server.js

const cors = require("cors");
const express = require("express");
const app = express();
global.__basedir = __dirname;
var corsOptions = {origin: "http://localhost:8081"};
app.use(cors(corsOptions));
const initRoutes = require("./src/routes");
app.use(express.urlencoded({ extended: true}));
initRoutes(app);
let port = 8080;
app.listen(port, () => {console.log(`Running at localhost:${port}`);
});

导入 express 和 cors 模块:

  • 创立 Express 利用,用于构建 Rest API,而后增加 cors 中间件。
  • 设置 http://localhost:8081 为 origin,这里容许前端传入

扩大浏览:《如何使 Vue ECharts 柱状图中,每个柱子色彩各不同(随机或指定色彩)》

运行后端并测试

首先,在 kalacloud-express-file-upload 根目录执行

node server.js

把后端服务启动起来。而后咱们应用 Postman 来发送 HTTP 申请,看看后端是否运行失常。

➜  kalacloud-express-file-upload node server.js
Running at localhost:8080

接着咱们应用 Postman 来测试一下,咱们刚刚搭建的后端服务器是否能失常运行

向后端服务器发 POST 申请上传文件

上传大于最大限度 (2MB) 的文件,500 报错。

GET 检索文件信息列表:

咱们能够应用返回的文件 URL 下载这些文件,例如:http://localhost:8080/files/kalacloud-logo.png

扩大浏览:《Video.js 应用教程 – 手把手教你基于 Vue 搭建 HTML 5 视频播放器》

Vue + Node.js 上传文件前后端一起运行

在 kalacloud-vue-multiple-files-upload 文件夹根目录运行前端 Vue

npm run serve

在 kalacloud-express-file-upload 文件夹根目录运行后端 Node.js

node server.js

而后关上浏览器输出前端拜访网址:

到这里整个前后端「上传文件」管理工具就搭建实现了。

Node.js 后端「上传文件」源码

你能够在我的 github 上下载到残缺的 Node.js 后端「上传文件」源码。

如果你还没搞懂,也不必焦急,间接应用卡拉云,无需懂任何前后端技术,仅需简略的鼠标拖拽即可疾速生成包含「上传文件」治理在内的任何后盾管理工具。立刻试用卡拉云。

「上传文件」前后端搭建总结

本教程手把手教大家搭建 Vue 前端 + Node.js 后端 的「文件上传」管理工具,如果你一步步跟着走,肯定曾经把 Demo 跑起来了。但如果你会应用最新的低代码开发工具「卡拉云」,齐全不须要这么繁琐,仅需 1 分钟,就能搭建起属于本人的「文件上传」管理工具。

注册开明卡拉云,从侧边工具栏间接拖拽组件到页面,生成上传组件和文件管理工具。1 分钟搞定「文件上传」管理工具。

扩大浏览:

  • Video.js 应用教程 – 手把手教你基于 Vue 搭建 HTML 5 视频播放器
  • 最好的 6 个收费天气 API 接口比照测评
  • 12 款最棒 Vue 开源 UI 库测评 – 特地针对国内应用场景举荐
  • 最棒的 7 个 Laravel admin 后盾管理系统举荐
  • Retool 是什么,怎么样?—— Retool 低代码工具测评
  • 最好用的 5 个 Vue select 单选多选下拉组件
  • 最好用的 7 款 Vue admin 后盾治理框架测评
退出移动版