今天踩了很多文件上传的坑,特此记录总结,方便广大网友查看。
废话不多说直接开始
官方文档 : https://element.eleme.cn/#/zh-CN/component/upload
<template>
<div>
<el-upload :action="'none'" :auto-upload="false" drag ref='upload' :on-change="onChange" :on-remove="onRemove" multiple show-file-list>
<i class="el-icon-upload">i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传em>div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kbdiv>
el-upload>
<el-button icon="el-icon-upload" type="primary" style="margin-top: 20px;" @click="submitUpload">上传el-button>
div>
template>
<script>
import config from '../../../../klcloud.config.js'
import api from '../../../api/index.js'
export default {
props: {
//设置文件保存的路径,作为参数传递进来
path: String
},
data() {
return {
//文件列表
fileList: [],
}
},
methods: {
//文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用
onChange(file,filelist){
//file.raw 才是真实的 file 对象
this.fileList.push(file.raw)
},
//文件列表移除文件时的钩子
onRemove(file, fileList){
//file.raw 才是真实的 file 对象
this.fileList.splice(this.fileList.indexOf(file.raw),1)
},
//上传文件
submitUpload() {
console.log("提交文件")
let formData = new FormData();
// 向 formData 对象中添加文件
this.fileList.forEach(file => {
formData.append('file', file);
})
//设置文件保存路径
// formData.append('path', this.path);
api.uploadFile(formData)
.then(r => {
console.log(r)
}).catch(e => {
console.log(e)
})
},
},
mounted() {
},
}
script>
<style scoped>
style>
属性 | 说明 |
---|---|
action | 表单提交地址,必填,我这里写 none 代表我们全权管理提交功能,不需要组件自动提交 |
auto-upload | 自动上传,我们不需要,所以设置false |
multiple | 多文件上传 |
show-file-list | 是否显示已上传文件列表 |
import request from '../utils/request.js'
export default {
uploadFile(formData){
//request : 封装好的axios 对象 ,下面具体说明
return new request({
url: `/api/file/upload`,
method: 'post',
data:formData
})
}
}
import axios from 'axios'
const service = axios.create({
baseURL:'http://localhost:8080', //这里是你基础url , url = baseURL + request url
timeout:20000,
})
export default service
用此片段代替上面的 vue template 的 submitUpload 函数
...
let formData = new FormData();
// 向 formData 对象中添加文件
this.fileList.forEach(file => {
formData.append('file', file);
})
//设置文件保存路径
formData.append('path', this.path);
//url 是你提交服务器的接口
axios.post(url,formData)
.then(r=>{
}).catch(e=>{
})
...
...
<el-dialog :title="'上传文件到: '+path" :visible.sync="uploadDialog">
<uploadFile :path="path">uploadFile>
el-dialog>
...
<script>
import uploadFile from './uploadFile.vue'
export default {
props: {
},
components:{
uploadFile
},
data() {
return {
path:'' // 设置文件上传到服务器的位置,比如服务器下有 public 目录, 你可以在这里写 ./public/
}
}
}
script>
//上传文件
app.post('/api/file/upload', (req, res) => {
//利用multiparty中间件获取文件数据
let uploadDir = './' //这个不用改,因为并不是保存在这个目录下,这只是作为中间目录,待会要重命名文件到指定目录的
let form = new multiparty.Form()
form.uploadDir = uploadDir
form.keepExtensions = true; //是否保留后缀
form.parse(req, function(err, fields, files) {
//其中fields表示你提交的表单数据对象,files表示你提交的文件对象
console.log("上传文件", fields)
console.log("files", files)
//这里是save_path 就是前端传回来的 path 字段,这个字段会被 multiparty 中间件解析到 fields 里面 ,这里的 fields 相当于 req.body 的意思
let save_path = fields.path
if (err) {
console.log(err)
res.send(formatReq(0, "上传失败"))
} else {
let file_list = []
if (!files.file) res.send(formatReq(0, "上传失败"))
else {
//所有文件重命名,(因为不重名的话是随机文件名)
files.file.forEach(file => {
/*
* file.path 文件路径
* save_path+originalFilename 指定上传的路径 + 原来的名字
*/
fs.rename(file.path, save_path + file.originalFilename, function(err) {
if (err) {
// console.log("重命名失败")
} else {
// console.log("重命名成功")
}
});
})
if (err) {
console.log(err)
res.send(formatReq(0, "上传失败"))
} else {
//返回所有上传的文件信息
res.send(formatReq(1, "上传成功"))
}
}
}
})
})
})
以下全部为 服务器端 demo 代码,仅供参考
var express = require('express');
var fs = require('fs');
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
var multiparty = require("multiparty")
//使用我自己的一些配置,主要就是配置端口,还有公开文件的路径
var config = require('./dist/klcloud.config.js')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({
extended: false
}))
//添加请求头
app.all('*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "content-type");
res.header("Access-Control-Allow-Methods", "GET,POST");
next();
});
// 读取当前文件夹下的所有文件
function walk(currentDirPath, callback) {
var list = []
var fs = require('fs'),
path = require('path');
fs.readdir(currentDirPath, function(err, files) {
if (err) {
callback()
} else {
for (let i = 0; i < files.length; i++) {
var filePath = path.join(currentDirPath, files[i]);
var stat = fs.statSync(filePath);
if (stat.isFile()) {
//添加文件信息
list.push({
file_name: files[i],
file_stat: stat,
file_path: filePath.replace(/\\/g, "/"),
is_file: true //是否为文件
});
} else if (stat.isDirectory()) {
list.push({
file_name: files[i],
file_stat: stat,
file_path: filePath.replace(/\\/g, "/"),
is_file: false
});
}
}
callback(list)
}
});
}
//统一格式化返回值
function formatReq(code, msg, data) {
return {
code: code,
data: data,
message: msg
}
}
// // 访问静态资源
app.use(express.static(path.resolve(__dirname, './dist/')));
// 访问单页
app.get('/', function(req, res) {
var html = fs.readFileSync(path.resolve(__dirname, './dist/index.html'), 'utf-8');
res.writeHead(200, {
"Content-Type": "text/html"});
res.send(html);
});
//获取路径下的文件
app.post('/api/file/open', (req, res) => {
console.log("获取路径下的文件", req.body);
let file_type = req.body.path.substring(req.body.path.lastIndexOf('.') + 1, req.body.path.length)
console.log(file_type)
//如果是图片
if (file_type.match(/(png|jpg|svg|gif|jpeg|ico)/)) {
fs.readFile(req.body.path,'binary',function(err,data){
if(err){
console.log(err)
}else{
console.log('数据读取成功');
const buffer = new Buffer.from(data, 'binary');
let src = 'data:image/'+ file_type +';base64,' + buffer.toString('base64');
res.send(formatReq(1, "获取成功", src))
}
});
} else {
var content = fs.readFileSync(req.body.path, 'utf-8');
res.send(formatReq(1, "获取成功", content))
res.end()
}
})
//获取路径下的所有文件
app.post('/api/file/list', (req, res) => {
console.log("获取路径下的文件夹", req.body);
walk(req.body.path, file_list => {
res.send(formatReq(1, "获取成功", file_list))
res.end()
})
})
//上传文件
app.post('/api/file/upload', (req, res) => {
//利用multiparty中间件获取文件数据
let uploadDir = './' //这个不用改,因为并不是保存在这个目录下,这只是作为中间目录,待会要重命名文件到指定目录的
let form = new multiparty.Form()
form.uploadDir = uploadDir
form.keepExtensions = true; //是否保留后缀
form.parse(req, function(err, fields, files) {
//其中fields表示你提交的表单数据对象,files表示你提交的文件对象
console.log("上传文件", fields)
console.log("files", files)
//这里是save_path 就是前端传回来的 path 字段,这个字段会被 multiparty 中间件解析到 fields 里面 ,这里的 fields 相当于 req.body 的意思
let save_path = fields.path
if (err) {
console.log(err)
res.send(formatReq(0, "上传失败"))
} else {
let file_list = []
if (!files.file) res.send(formatReq(0, "上传失败"))
else {
//所有文件重命名,(因为不重名的话是随机文件名)
files.file.forEach(file => {
/*
* file.path 文件路径
* save_path+originalFilename 指定上传的路径 + 原来的名字
*/
fs.rename(file.path, save_path + file.originalFilename, function(err) {
if (err) {
// console.log("重命名失败")
} else {
// console.log("重命名成功")
}
});
})
if (err) {
console.log(err)
res.send(formatReq(0, "上传失败"))
} else {
//返回所有上传的文件信息
res.send(formatReq(1, "上传成功"))
}
}
}
})
})
//创建文件夹
app.post('/api/folder/create', (req, res) => {
console.log("创建文件夹", req.body);
fs.mkdir(req.body.path, (err) => {
if (err) {
console.log(err);
res.send(formatReq(0, "创建文件夹失败"))
} else {
res.send(formatReq(1, "创建文件夹成功"))
}
res.end()
});
})
//创建文件
app.post('/api/file/create', (req, res) => {
console.log("创建文件", req.body);
fs.writeFile(req.body.path, "", (err) => {
if (err) {
console.log(err);
res.send(formatReq(0, "创建文件失败"))
} else {
res.send(formatReq(1, "创建文件成功"))
}
res.end()
});
})
//删除目录
app.post('/api/folder/remove', (req, res) => {
console.log("删除目录", req.body);
fs.rmdir(req.body.path, (err) => {
if (err) {
console.log(err);
res.send(formatReq(0, "删除文件夹失败"))
} else {
res.send(formatReq(1, "删除文件夹成功"))
}
res.end()
})
})
//删除文件
app.post('/api/file/remove', (req, res) => {
console.log("删除文件", req.body);
fs.unlink(req.body.path, (err) => {
if (err) {
console.log(err);
res.send(formatReq(0, "删除文件失败"))
} else {
res.send(formatReq(1, "删除文件成功"))
}
res.end()
})
})
app.get('/api/login/:account/:password', function(req, res) {
if (req.params.account =='admin' && req.params.password == '132525') {
res.send({
code: 1,
message: '登录成功'
});
} else {
res.send({
code: 0,
message: '登录失败'
});
}
res.end()
});
// 监听
app.listen(config.port, function() {
console.log('success listen in port:' + config.port, '\nyour login info : ' + JSON.stringify(config.login));
});