koa2上传图片同步七牛云存储

1,604 阅读3分钟

前言

  • 【音乐博客】音乐文件服务器没空间容下它们,所以它们投奔向了七牛云


六个方面

1. 七牛云

  • 七牛云就是一个文件服务器,我通过七牛云提供的接口,然后前端将文件上传上去,上传成功会给我key,我就可以拼接出文件的路径访问

2. 脚手架搭koa2服务并安装qinniu包

  • npm i qiniu --save-dev

3. 主要controllar代码

  • const router = require('koa-router')()
    var uuid = require('uuid');
    let func = require('qianniuyun');  /*导入七牛文件   */
    const formidable = require('formidable');
    var fs = require('fs');
    var path = require('path');
    var DB = require('../../utils/mysqlDB')
    
    router.prefix('/music')
    
    
    
    router.post('/upload', async (ctx, next) => {
    
      const musicInfo = JSON.parse(ctx.request.body.musicInfo);
    
    
      let result = {}
    
      try {
        // 前端必须以formData格式进行文件的传递
        // const file = ctx.request.files.file0; // 获取上传文件
    
        let fileArr = Object.entries(ctx.request.files) 
    
        if (fileArr.length != 0) {
          result = await uploadToQiniu(fileArr)
    
          console.log(result)
          // 因为我现在是想插入到同一行,所以就不循环了
          // result.forEach(async element => {
    
          //   await DB.query(`
          //       insert into qiniu_music(id,file_hash,file_key,username,file_type,file_name,file_size,is_sucess, song_name, singer_name, song_type)
          //       values('${element.id}','${element.hash}','${element.key}','${ctx.request.body.username}','${element.fileType}','${element.fileName}','${element.fileSize}','${element.isSucess}', '${musicInfo.songName}', '${musicInfo.singerName}', '${musicInfo.songType}')
          //   `)
          // });
    
          // 插入到同一行
          // qiniu_music和qiniu_song_img,两个表的id是一样的,所以到时候可以做下关联
          await DB.query(`
                    insert into qiniu_music(id,file_hash,file_key,username,file_type,file_name,file_size,is_sucess, song_name, singer_name, song_type)
                    values('${result[0].id}','${result[0].hash}','${result[0].key}','${ctx.request.body.username}','${result[0].fileType}','${result[0].fileName}','${result[0].fileSize}','${result[0].isSucess}', '${musicInfo.songName}', '${musicInfo.singerName}', '${musicInfo.songType}')
                `)
    
          await DB.query(`
                    insert into qiniu_song_img(id,file_hash,file_key,file_type,file_name,file_size,is_sucess)
                    values('${result[0].id}','${result[1].hash}','${result[1].key}','${result[1].fileType}','${result[1].fileName}','${result[1].fileSize}','${result[1].isSucess}')
                `)
    
     
    
          if (result) {
            console.log("上传成功")
            ctx.response.body = result
          } else {
            console.log(333)
            ctx.response.body = "上传失败!"
          }
        } else {
          console.log(4444)
          ctx.response.body = "没有选择图片"
        }
      } catch (err) {
        console.log(err)
        console.log("err544")
        ctx.response.body = "err"
      }
    
      ctx.body = {
        code: 20000,
        result
      }
    })
    
    
    // 支持多文件上传到千牛云
    const uploadToQiniu = (fileArr) => {
      var promiseTmp = []
      fileArr.forEach(element => {
    
        promiseTmp.push(new Promise((resolve, reject) => {
          // 命名文件
          const fileName = uuid.v1();
          // 创建文件可读流
          const reader = fs.createReadStream(element[1].path);
          // 获取上传文件扩展名
          const ext = element[1].name.split(".").pop();
          // 命名文件以及拓展名
          const fileUrl = `${fileName}.${ext}`;
    
          // 调用方法(封装在utils文件夹内)
          func.upToQiniu(reader, fileUrl).then(res => {
            let tmp = {
              id: fileName,
              hash: res.hash,
              key: res.key,
              fileType: element[1].type,
              fileName: element[1].name,
              fileSize: element[1].size,
              isSucess: 1
            }
    
            resolve(tmp)
          })
        }));
    
      });
    
    
      return Promise.all(promiseTmp).then((result) => {
        return result
      })
    }
    
    
    module.exports = router

4. 查看utils中的upload.js代码

  • var uuid = require('uuid');
    var fs = require('fs');
    // 上传到七牛
    let qiniu = require('qiniu'); // 需要加载qiniu模块的
    // 引入key文件
    const QINIU = require('qiniu.js')
    const upToQiniu = (filePath, key) => {
        const accessKey = QINIU.accessKey
        const secretKey = QINIU.secretKey
        const mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
        // bucket是存储空间名称
        const options = {
          scope: QINIU.bucket
        }
        const putPolicy =  new qiniu.rs.PutPolicy(options);
        // 生成token 作为个人七牛云账号的识别标识
        const uploadToken= putPolicy.uploadToken(mac);
      
        const config= new qiniu.conf.Config()
        // 空间对应的机房 一定要按自己属区Zone对象
    
        const localFile = filePath
        const formUploader = new qiniu.form_up.FormUploader(config)
        const putExtra = new qiniu.form_up.PutExtra()
        // 文件上传
        return new Promise((resolved, reject) => {
          // 以文件流的形式进行上传
          // uploadToken是token, key是上传到七牛后保存的文件名, localFile是流文件
          // putExtra是上传的文件参数,采用源码中的默认参数
          formUploader.putStream(uploadToken, key, localFile, putExtra, function (respErr, respBody, respInfo) {
            if (respErr) {
              reject(respErr)
            } else {
              resolved(respBody)
            }
          })
        })
      }
    
    
      
    
    // 支持多文件上传到千牛云
    const uploadToQiniu = (fileArr) => {
      var promiseTmp = []
      fileArr.forEach(element => {
    
        promiseTmp.push(new Promise((resolve, reject) => {
          // 命名文件
          const fileName = uuid.v1();
          // 创建文件可读流
          const reader = fs.createReadStream(element[1].path);
          // 获取上传文件扩展名
          const ext = element[1].name.split(".").pop();
          // 命名文件以及拓展名
          const fileUrl = `${fileName}.${ext}`;
    
          // 调用方法(封装在utils文件夹内)
          upToQiniu(reader, fileUrl).then(res => {
            let tmp = {
              id: fileName,
              hash: res.hash,
              key: res.key,
              fileType: element[1].type,
              fileName: element[1].name,
              fileSize: element[1].size,
              isSucess: 1
            }
    
            resolve(tmp)
          })
        }));
    
      });
    
    
      return Promise.all(promiseTmp).then((result) => {
        return result
      })
    }
    
    
      module.exports = {
        upToQiniu,
        uploadToQiniu
        
    }

5. 请看key文件配置信息

  • 此配置信息需要登录七牛云账号去获取
  • qiniu.js
  • let QINIU  = {};
    QINIU.accessKey = 'CQW4';
    QINIU.secretKey = 'eRkmVBXPSPMr';
    QINIU.bucket = 'dignity';  //存储空间的名字
    QINIU.origin = 'xxx.com';  //配置的域名
    module.exports = QINIU;

6. 使用七牛云上传文件报错error=incorrect region, please use up-z2.qiniu.com

  • 在使用七牛云上传文件可能会报一个错:
  • info ===== <QNResponseInfo= id: CB441DB1-B50D-472A-8DAB-B07700E102C5, ver: 7.1.6, status: 400, 
    requestId:XXXX, XXXX, xlog: RA:122.224.95.105:80;UP/400;NUPROXY:28/400, 
    xvia: (null), host: upload.qiniu.com ip: 180.97.72.163 duration: 0.068638 s time: 1503737206 
    error: Error Domain=qiniu.com Code=400 “(null)” UserInfo={error=incorrect region, please use up-z2.qiniu.com}>

  • 问题原因:
  • 创建七牛云存储空间时选择了华南地区,但上传文件的配置类中配置了其他地区
  • 解决方法:
  • 在配置Configuration类的时候,按需选择Zone的类型即可
  •  //Zone.zone0:华东 
        //Zone.zone1:华北 
        //Zone.zone2:华南 
        //Zone.zoneNa0:北美 
        //———http上传,自动识别上传区域—— 
        //Zone.httpAutoZone 
        //———https上传,自动识别上传区域—— //Zone.httpsAutoZone

  • //指定上传文件服务器地址:
                Configuration cfg = new Configuration(Zone.zone2());

  • 七牛云你注册的时候是有选地区的,要记住自己是什么地区,然后代码中也要写对地区,才可以上传对应成功。

最后总结

如果真的要使用七牛云作为存储文件的同学,就上传图片就好,普通用户每个月要10G流量应该够个人用,不像我,一开始不知道,上传都是无损音乐,一首歌30M以上,天天听,结果就悲剧了,过上扣费交钱的生活...
如果想用本机作为服务器的同学,请移步(内网穿透了解一下):juejin.cn/post/684490…
关于想了解koa上传文件的同学,请移步:juejin.cn/post/684490…

原文地址

juejin.cn/post/684490…


参考

koa2上传图片同步七牛云存储,代码已postman测试,perfect!!!!! :blog.csdn.net/weixin_4424…

使用七牛云上传文件报错error=incorrect region, please use up-z2.qiniu.com:blog.csdn.net/weixin_4556…