最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 基于node的文件上传和下载

    正文概述 掘金(forever_Mamba)   2021-08-11   344

    “这是我参与8月更文挑战的第10天,活动详情查看: 8月更文挑战” juejin.cn/post/ 6987962113788493831”

    前言

    未来的日子,愿你吧自己调至最佳状态,缓缓努力,慢慢变好 Y(^o^)Y

    技术栈准备:

    1. 使用了一个基于 node 的处理 Excel 文件的三方库 node-xlsx
    2. 文件处理过程涉及到文件名称的格式编码,使用到一个编码库 urlencode

    文件导出

    1. 生成文件名称

    通常文件名称可能会依赖数据库的数据,比如:${name}-${version}.xlsx

    最终我们需要是 eg:手机号码-20191010.xlsx

    使用 urlencode 编码生成文件名称

    简单粗暴直接上代码

    const fileName = urlencode(`${projectName}-${versionId}.${fileType}`, 'utf-8');
    
    1. 生成表格数据

    一般我们从数据库查询到的数据都是 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文件失败!')
      }
    
    
    1. 生成一个 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
        ....
    
      }
    
    
    

    至此,文件的上传和导出已经完成,代码直接可以使用?

    结语

    如果这篇文章帮到了你,欢迎点赞?和关注⭐️

    文章如有错误之处,希望在评论区指正??。


    起源地下载网 » 基于node的文件上传和下载

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元