node基于“multipart / form-data“转发表单上传文件到后台
过程:后台(go)+ 中间(node)+前端(vue)使用node进行中间层转发,前端使用form-data进行数据上传,传递给node,node使用form-data将数据传给后端(go)前端上传excel页面效果:页面布局实现:(使用elementui框架)<el-uploadclass="upload-demo"ref="fileupload"accep...
·
过程:
后台(go)+ 中间(node - express)+前端(vue)
使用node进行中间层转发,前端使用form-data进行数据上传,传递给node,node使用form-data将数据传给后端(go),成功后将文件在oss进行备份
前端上传excel
页面效果:
1.页面布局实现:(使用elementui框架)
<el-upload
class="upload-demo"
ref="fileupload"
accept=".xls,.xlsx" // 接受上传文件类型
action="##" // 上传地址,由于上传文件成功还需执行其他,所以写##
:before-upload="beforeUpload" // 上传文件之前的钩子
:http-request="uploadSectionFile" // 覆盖默认的上传行为,可自定义上传实现
drag // 是否启动拖拽上传
v-loading='uploadFlag'>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传xlsx文件</div>
</el-upload>
2.上传之前校验文件内容是否符合要求,使用js-xlsx解析文件,下面以判断文件中日期是否一致为例
如未安装js-xslx,需先安装
npm install xlsx
接下来在页面中引入
import XLSX from 'xlsx';
在校验文件中调用XLSX
beforeUpload(file) {
const that = this;
// 使返回的值变成Promise对象,如果校验不通过,则reject,校验通过,则resolve
return new Promise((resolve, reject) => {
// readExcel方法也使用了Promise异步转同步,此处使用then对返回值进行处理
that.readExcel(file).then((result) => { // 此时标识校验成功,为resolve返回
if (result) {
resolve('校验成功!');
} else {
that.$message.error('请检查文件内容日期是否一致');
}
}, (error) => { // 此时为校验失败,为reject返回
that.$message.error(error);
});
});
},
// 解析Excel,查看文件中的日期是否一致
readExcel(file) {
return new Promise((resolve, reject) => { // 返回Promise对象
const reader = new FileReader();
let data,
workbook;
reader.onload = (e) => { // 异步执行
try {
// 以二进制流方式读取得到整份excel表格对象
data = e.target.result;
workbook = XLSX.read(data, { type: 'binary' });
} catch (ev) {
reject(ev.message);
}
// 表格的表格范围,判断第一列内容是否正确
// 遍历每张表读取
if (workbook.Sheets.length > 1) {
resolve(false);
} else {
for (const sheet in workbook.Sheets) {
if (Object.prototype.hasOwnProperty.call(workbook.Sheets, sheet)) {
const sheetInfos = workbook.Sheets[sheet];
let locations = '';
for (const key in sheetInfos) {
if (Object.prototype.hasOwnProperty.call(sheetInfos, key)) {
const reg = /[A]/g;
if (reg.test(key) && key !== 'A1') {
if (locations === '') {
locations = sheetInfos[key].w;
} else if (locations !== sheetInfos[key].w) {
resolve(false);
}
}
}
}
const newlocations = locations.split('/');
let month,
day;
if (newlocations[0] < 10) {
month = `0${newlocations[0]}`;
} else {
month = newlocations[0];
}
if (newlocations[1] < 10) {
day = `0${newlocations[1]}`;
} else {
day = newlocations[1];
}
const nowDate = `20${newlocations[2]}-${month}-${day}`;
this.Evalue = nowDate;
this.Svalue = nowDate;
}
}
resolve(true);
}
};
reader.readAsBinaryString(file);
});
},
3.前端上传文件到node
uploadSectionFile(item) {
const form = new FormData();
// 文件对象
form.append('file', item.file);
this.$axios({
method: 'post',
url: "node请求地址"
data: form,
}).then((res) => {
// 写自己的代码逻辑
});
},
4.node接收到的参数req.files如下
{ file:
{ fieldName: 'file',
originalFilename: 'xxxxxx.xlsx',
path:
'/var/folders/k9/jc7jb8w91yqb2w85rkppsj8m0000gn/T/4mDO8jEdeVixVNV11RcVAcS_.xlsx',
headers:
{ 'content-disposition':
'form-data; name="file"; filename="xxxxxx.xlsx"',
'content-type':
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' },
size: 13360,
name: 'xxxxxx.xlsx',
type:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }
}
需要将req.files中的file参数用from-data传递给后端(go)
使用form-data创建可读的“ multipart / form-data”流的模块。
安装form-data模块
npm install form-data
const FormData = require('form-data')
const fs = require('fs');
const path = require('path');
const { path: filePath, originalFilename } = req.files.file
const newPath = path.join(path.dirname(filePath), originalFilename) // 得到newPath新地址用于创建读取流
const user_name = req.body.username;
fs.rename(filePath, newPath, (err) => {
if (err) {
return;
} else {
const file = fs.createReadStream(newPath) //创建读取流
const form = new FormData() // new formdata实例
form.append('upload', file) // 把文件加入到formdata实例中
request({
method: 'post',
url:'后端接口',
body:form,
headers: form.getHeaders() //formdata的headers
},function(error, response, body) {
if (!error && response.statusCode == 200) {
res.send(body)
} else{
res.send(error)
}
})
}
})
5.成功后在oss进行文件备份
upload(item) {
const client = new OSS({
region: 'Your bucket name', //比如:oss-cn-beijing
accessKeyId: 'Your accessKeyId',
accessKeySecret: 'Your accessKeySecret',
bucket: 'Your bucket name',
}),
object = item.file.name; //上传文件名称
client.put(object, item.file).then((r1) => {
if (r1) {
this.$message.success('上传成功');
}
}).then((r2) => {
if (r2) {
this.$message.success('上传成功');
}
}).catch((err) => {
this.$message.error(err);
});
},
如果oss中文件已存在,则添加编号(0 -100)比如xxxx1.xslx
/*
* 判断oss中文件是否存在
* client oss配置信息
* object 文件名称
* item 要上传的文件
*/
fileTest(client, object, item) {
client.get(object).then((result) => {
if (result.res.status === 200) {
this.modifyFileName(client, object, item);
}
}).catch((e) => {
if (e.code === 'NoSuchKey') {
client.put(object, item.file).then((r1) => {
if (r1) {
this.upload(item);
}
}).then((r2) => {
if (r2) {
this.upload(item);
}
}).catch((err) => {
this.$message.error(err);
});
}
});
},
/*
* 修改上传文件名称
*/
modifyFileName(client, object, item) {
const newObject = object.split('.'),
reg = /^\d*$/;
let num = newObject[0][newObject[0].length - 1];
if (reg.test(num)) {
const newNum = newObject[0].substring(newObject[0].length - 2);
if (reg.test(newNum)) {
num = Number(newNum);
} else {
num = Number(num);
}
num += 1;
} else {
num = 1;
}
const name = item.file.name.split('.'),
newName = `${name[0]}${window.localStorage.getItem('username')}${num}.${newObject[1]}`;
this.fileTest(client, newName, item);
},
更多推荐
已为社区贡献2条内容
所有评论(0)