1.前端代码
<template>
<div class="upload_container">
<el-progress :percentage="progressNum" />
<input type="file" ref="file" @change="selectFile" />
<el-button type="primary" @click="uploadFile">上传文件</el-button>
</div>
</template>
<script setup lang="ts">
import axios from "axios";
import { reactive, ref } from "vue";
import { ElMessage } from "element-plus";
const file = ref(null); //
const selectFileobj = ref(null); //用来保存选择的文件
const progressNum = ref(0); //进度条
const chunk_size = ref(10 * 1024 * 1024); //分片大小为10M
const uploadSize = ref(0); //已上传的文件大小
//选择文件
const selectFile = () => {
console.log(file.value?.files); //获取到文件对象
if (file.value?.files[0]) {
selectFileobj.value = file.value?.files[0];
}
};
//上传文件
const uploadFile = async () => {
if (selectFileobj.value) {
console.log("selectFileobj: ", selectFileobj.value);
const { name, size, type } = selectFileobj.value;
while (uploadSize.value < size) {
//已上传的文件大小小于时
const fileChunk = selectFileobj.value?.slice(
uploadSize.value,
uploadSize.value + chunk_size.value
);
console.log("fileChunk: ", fileChunk); //得到每次切片好的文件
const fd = new FormData();
fd.append("name", name);
fd.append("type", type);
fd.append("size", size);
fd.append("uploadSize", uploadSize.value);
fd.append("file", fileChunk);
const res = await axios.post("http://localhost:8000/upload_file", fd);
console.log("res:上传文件 ", res);
uploadSize.value += fileChunk.size;
progressNum.value = (uploadSize.value / size).toFixed(2) * 100 //进度条控制
}
} else {
ElMessage({
message: "请选择文件",
type: "warning",
});
}
};
</script>
<style scoped>
.upload_container {
width: 200px;
text-align: left;
}
</style>
2.后端node.js
var express = require("express");
const bodyParser = require("body-parser");
const uploader = require("express-fileupload"); //express-fileupload插件
const { extname, resolve } = require("path");
const { existsSync, appendFileSync, writeFileSync } = require("fs"); //文件读写
// 实例化express
var app = express();
//配置bodyparser 解析的作用 固定写法
app.use(bodyParser.json()); //解析json
app.use(bodyParser.urlencoded()); //解析表单数据
app.use(uploader()); //此中间件是为了拿到前端传的文件类型的数据
app.use("/", express.static("file"));
//跨越处理
app.all("*", (req, res, next) => {
res.header("Access-Control-Allow-origin", "*");
res.header("Access-Control-Allow-Methods", "POST,GET");
next();
});
app.post("/upload_file", (req, res) => {
// console.log("req: ", req);
// 获取前端上传的参数
const { name, type, size, uploadSize } = req.body;
const { file } = req.files; //文件
const filePath = resolve(__dirname, "./file/" + name); //拼接路径
if (uploadSize !== "0") {
if (!existsSync(filePath)) {
res.send({
code: 400,
message: "no file exists",
});
return;
}
//写文件
appendFileSync(filePath, file.data);
res.send({
code: 200,
message: "padding",
data: {
videoUrl: "http://localhost:8000/" + name, //将url返回给前端展示
},
});
} else {
writeFileSync(filePath, file.data); //创建并开始写文件
res.send({
code: 200,
message: "file is created",
});
}
});
app.listen(8000, function () {
console.log("服务已启动,端口8000");
});