“这是我参与8月更文挑战的第10天,活动详情查看: 8月更文挑战” juejin.cn/post/ 6987962113788493831”
前言
未来的日子,愿你吧自己调至最佳状态,缓缓努力,慢慢变好 Y(^o^)Y
技术栈准备:
- 使用了一个基于 node 的处理 Excel 文件的三方库 node-xlsx
- 文件处理过程涉及到文件名称的格式编码,使用到一个编码库 urlencode
文件导出
- 生成文件名称
通常文件名称可能会依赖数据库的数据,比如:${name}-${version}.xlsx
最终我们需要是 eg:手机号码-20191010.xlsx
使用 urlencode 编码生成文件名称
简单粗暴直接上代码
const fileName = urlencode(`${projectName}-${versionId}.${fileType}`, 'utf-8');
- 生成表格数据
一般我们从数据库查询到的数据都是 Array 格式,所以可以直接处理一下转为 xlsx 的格式
组装我们需要的数据,生成表格的表头,最后返回一个 buffer,这样在浏览器中就直接自动下载。
const dataArray = [......];
/**
* 组装Excel数据
*/
let xlsxArr = [] // 表格数据
let first = ['key'] // 表格表头
dataArray.forEach(ele => {
let arrRow = []
arrRow.push(ele.contentKey)
ele.contentValues.forEach(item => {
arrRow.push(item.content)
if(!first.includes(item.language)){
first.push(item.language)
}
})
xlsxArr.push(arrRow)
})
xlsxArr.unshift(first)
try {
const options = { '!cols': first.map(() => ({ wch: 50 })) }; // 设置表格列宽
var buffer = xlsx.build([{name: "mySheetName", data: xlsxArr}], options); // returns a buffer
// 设置响应的类型为 stream 格式
ctx.type = 'application/octet-stream'
// 设置 Content-Disposition
ctx.set("Content-Disposition", "attachment; filename* = UTF-8''"+fileName)
ctx.body = buffer;
} catch (e) {
console.log(e)
throw new Error('生成excel文件失败!')
}
- 生成一个 json 格式的文件
将从数据库查询的数据进行 json 化处理
let json = {};
// 将数据json化处理
dataArray.forEach(ele => {
ele.contentValues.forEach(item => {
if (json.hasOwnProperty(item.language)) {
json[item.language][ele.contentKey] = item.content;
} else {
json[item.language] = {};
json[item.language][ele.contentKey] = item.content;
}
});
});
ctx.type = 'application/octet-stream'
ctx.set("Content-Disposition", "attachment; filename* = UTF-8''"+fileName)
ctx.body = JSON.stringify(json, null, 2)
文件上传
解析.json 或者 .xlsx 文件的数据
/**
* 接收 .json 或者 .excel 格式的文件
*/
const fileType = ctx.request.body.filename.indexOf('.json')
// 获取上传的文件夹地址
const uploadDir = os.tmpdir()
try {
// 将文件中数据接口解析成数据库中需要的格式
let dataList
if(fileType === -1) { // .excel文件
// 使用 xlsx 库解析文件
const obj = xlsx.parse(uploadDir + '/' + ctx.request.body.filename);
const excelData = obj[0].data
const excelHeader = excelData[0]
const fileData = excelData.splice(1)
dataList = _.reduce(fileData, (result, value) => {
if(Array.isArray(value)) {
excelHeader.forEach((item, key) => {
if(key === 0) {
result[value[0]] = result[value[0]] ? result[value[0]] : []
} else if(key !==0) {
if(value[key]) {
result[value[0]].push({ content: value[key], language: item})
}
}
})
return result
} else {
throw new Error('格式不符合要求!')
}
}, {})
} else { // .json文件
let resourceJson = JSON.parse(fs.readFileSync(uploadDir + '/' + ctx.request.body.filename, {encoding: 'utf-8'}))
// let resourceJson = require(uploadDir + '/' + ctx.request.body.filename)
dataList = _.reduce(resourceJson, (result, value, key) => {
if(typeof value === 'object') {
Object.keys(value).forEach(ret => {
result[ret] = result[ret] ? result[ret] : []
result[ret].push({ content: value[ret], language: key })
})
return result
} else {
throw new Error('格式不符合要求!')
}
},{})
}
// 接下来就是 将数据分类成插入和更新两种操作
....
dataList 数据库的 insert 和 update
....
}
至此,文件的上传和导出已经完成,代码直接可以使用?
结语
如果这篇文章帮到了你,欢迎点赞?和关注⭐️
文章如有错误之处,希望在评论区指正??。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!