node笔记_express结合formidable实现前后端的文件上传
文章目录
- ⭐前言
- ⭐安装http请求的文件解析依赖库
- 💖 安装 formidable
- 💖 node formidable接受formData上传参数
- ⭐上传的页面搭建
- 💖 vue2 element upload
- 💖 node 渲染 上传文件
- ⭐后端生成api上传文件到指定目录
- 💖完整的代码块
- 💖效果图
- ⭐结束
⭐前言
大家好,我是yma16,本期分享node使用express结合formidable实现前后端联调的文件上传
往期文章
node_windows环境变量配置
node_npm发布包
linux_配置node
node_nvm安装配置
node笔记_http服务搭建(渲染html、json)
node笔记_读文件
node笔记_写文件
node笔记_连接mysql实现crud
⭐安装http请求的文件解析依赖库
💖 安装 formidable
$ npm install formidable
💖 node formidable接受formData上传参数
查看 readme的介绍
const hostname = '127.0.0.1';
const port = 3000;
const express = require("express");
const formidable = require('formidable');
const app = express();
app.listen(port, hostname, () => {console.log(`Server running at http://${hostname}:${port}/`);
});
app.get("/", (req, res) => {console.log(__dirname)res.json({code: 200,data: 'yma16 blog',msg: 'csdn node challenge'})
});app.post('/uploadFile/action', (req, res, next) => {// parse a file uploadconst form = new formidable({multiples: true});// parse 解析form.parse(req, (err, fields, files) => {console.log('req', req)console.log('err,', err)console.log('fields,', fields)console.log('files,', files)if (err) {next(err);return;}// json返回res.json({fields,files});})
})
⭐上传的页面搭建
使用formData上传二进制文件
💖 vue2 element upload
这里使用vue2和element实现上传
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>elementui vue2 上传文件</title><!-- vue2 生产环境版本,优化了尺寸和速度 --><script src="https://cdn.jsdelivr.net/npm/vue@2"></script><!-- 引入样式 --><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><!-- 引入组件库 --><script src="https://unpkg.com/element-ui/lib/index.js"></script><!-- axios --><script src="https://unpkg.com/axios/dist/axios.min.js"></script></head><style>#app {position: absolute;height: 100vh;width: 100vw;}.upload-container {position: relative;width: 100%;height: 100%;}.upload-container-box {position: absolute;left: 50%;top: 50%;transform: translate(-50%, -50%);}.container-title {position: relative;width: 100%;font-size: 24px;font-weight: bold;text-align: center;}</style><body><div id="app"><div class="container-title">{{ message }}</div><div><!-- 文件上传 先关闭自动上传--><div class="upload-container-box"><template><!-- :action="uploadForm.uploadUrl"--><el-upload class="upload-demo" :accept="uploadForm.accept" ref="uploadRef" drag:onRemove="handleRemove" :onChange="handlChange" :beforeUpload="beforeUpload":action="uploadForm.uploadUrl" :autoUpload="uploadForm.autoUpload":fileList="uploadForm.fileList" list-type="picture" :httpRequest="designUpload"><i class="el-icon-upload"></i><div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div><div class="el-upload__tip" slot="tip">只能上传单个png、jpg文件</div></el-upload><div style="text-align: center"><el-button type="primary" plain @click="submitBtn"style="margin-top:10px">上传到服务器</el-button></div></template></div></div></div><script type="text/javascript">// ELEMENT.Messageconst {Message}=Element;// instanceconst instanceVue = {el: '#app',name:'upload-component',data() {const uploadTypeForm = {text: ["jpg", "png", "jpeg", "svg"]};return {message: 'element 自定义上传',$message:Message,uploadForm: {autoUpload: false,accept: uploadTypeForm.text.join(","),uploadUrl: "http://localhost:3000/uploadFile/action", //上传的url 默认空fileList: []}};},methods: {/*** 文件删除回调*/handleRemove(file, fileList) {this.uploadForm.fileList = fileList;},/*** 选择文件时回调*/handlChange(file, fileList) {this.uploadForm.fileList = fileList;},//上传前的回调beforeUpload: function(file) {console.info("上传前的钩子", file);// 关闭自动上传return false},submitBtn() {if (this.uploadForm.fileList.length <= 0) {this.$message({message: "请先选择文件!",type: "error"});}this.$refs.uploadRef.submit(); //触发自定义上传},//自定义上传designUpload(params) {console.info("自定义上传", params);const that = this;const formData = new FormData();formData.append("file", params.file);const header = {"Content-Type": "mutipart/form-data"};//上传的后端接口const upLoadUrl = that.uploadForm.upLoadUrl;axios({url: upLoadUrl,method: "post",data: formData,headers: header}).then(res => {console.info("res", res);params.onSuccess(); //成功iconthat.$message({message: "上传成功!",type: "success"});}).catch(r => {that.$message.error("上传失败!");throw Error(r);});}},}// 实例化new Vue(instanceVue);</script></body>
</html>
上传file参数是二进制文件
💖 node 渲染 上传文件
const hostname = '127.0.0.1';
const port = 3000;
const express = require("express");
const app = express();app.listen(port,hostname, () => {console.log(`Server running at http://${hostname}:${port}/`);
});
// server your css as static
app.use(express.static(__dirname));app.get("/", (req, res) => {res.json({code:200,data:'yma16 blog',msg:'csdn node challenge'})
});
app.get("/uploadFile", (req, res) => {res.sendFile(__dirname + "/html/upload.html");
});
渲染 upload.html
⭐后端生成api上传文件到指定目录
- 先渲染html的上传页面
- 接受文件参数
- 处理文件名,避免重名,加上时间撮处理
💖完整的代码块
指定 media为上传路径,生成文件名加上时间搓
const hostname = '127.0.0.1';
const port = 3000;const express = require("express");
const formidable = require('formidable');
const fs = require('fs')
const app = express();app.listen(port, hostname, () => {console.log(`Server running at http://${hostname}:${port}/`);
});
// server your css as static
app.use(express.static(__dirname));app.get("/", (req, res) => {console.log(__dirname)res.json({code: 200,data: 'yma16 blog',msg: 'csdn node challenge'})
});app.get("/uploadFile", (req, res) => {console.log(__dirname)res.sendFile(__dirname + "/html/upload.html");
});function generateFilename(oldFilename) {//将老的文件名拼上时间戳let d = new Date();let names = oldFilename.split(".");return `${names[0]}_${""+d.getFullYear() + (d.getMonth()+1) + d.getDate() +'_'+ d.getHours() + d.getMinutes() + d.getSeconds()}.${names[1]}`;
}app.post('/uploadFile/action', (req, res, next) => {// parse a file upload// const form = new formidable({multiples: true});// api回调const form = new formidable.IncomingForm();//保持原有扩展名form.keepExtensions = true;//设置上传目录form.uploadDir = __dirname + "/media/";// parse 解析form.parse(req, async(err, fields, files) => {console.log('req', req)console.log('err,', err)console.log('fields,', fields)console.log('files,', files)if (err) {next(err);return;}try {console.log('files.file', files.file)// 默认名称const originalFilename = files.file.originalFilename;// 默认的路径const filePath= files.file.filepath//重命名上传的文件fs.rename(filePath, form.uploadDir + generateFilename(originalFilename), err => {if (err) {console.log("重命名失败");console.log(err);} else {console.log("重命名成功!");}})} catch (r) {next(r)return}// json返回res.json({fields,files});})
})
得到的文件流对象
💖效果图
前端的接口联调
后端node处理生成的文件
⭐结束
感谢阅读💖,如有不足欢迎指出!