博主正在重构博客中,刚开始时静态资源都是上传到本地服务器的,但这个项目博主最后打算真正上线运营的。索性就改进了下,把静态资源尽量放到云存储中,方便后续开发。这里把方法和遇到坑给记录下。

1.使用前提

  • 注册七牛云并创建存储空间
  • 在秘钥管理中拿到 AccessKey/SecretKey

2.工作原理

上传文件到七牛有客户端上传和服务器上传两种方式,这里我们选择客户端上传,上传前从后端获取token,再通过客服端直接上传。获得上传成功后的key值,拼接上路径前缀,即是文件的资源路径,再将资源路径存入到数据库中。

3.后端接口搭建

npm install qiniu
import Router from 'koa-router'
import axios from './utils/axios'
import qiniu from 'qiniu'

//需要填写你的 Access Key 和 Secret Key
const accessKey = '你的 Access Key'
const secretKey = '你的 Secret Key'
//要上传的空间
const bucket = '要上传的空间'

//声明路由
let router = new Router({ prefix: '/qiniu' })

//登录接口
router.post('/upload', async (ctx, next) => {
  //上传到七牛后保存的文件名
  let key = ctx.request.body.key
  //生成上传 Token
  //   console.log(key, bucket)
  let mac = new qiniu.auth.digest.Mac(accessKey, secretKey)
  let putPolicy = new qiniu.rs.PutPolicy({ scope: bucket })
  // 生成上传文件的 token
  let uptoken = putPolicy.uploadToken(mac)
  if (uptoken) {
    ctx.body = {
      code: 0,
      msg: '获取上传token成功',
      uptoken
    }
  } else {
    ctx.body = {
      code: -1,
      msg: '获取token失败'
    }
  }
})

export default router

更多功能可参考官方SDK文档

4.前端页面搭建

上传文件组件,根据存储区域不同设置action(具体可通过产品手册查看),请求携带参数通过data绑定

<el-form-item id="uploderitem" label="文章封面" prop="post_bg">
          <el-upload
            class="avatar-uploader"
            id="imguplad"
            action="https://upload.qiniup.com"
            :data="qn"
            :show-file-list="false"
            :on-success="handleAvatarSuccess"
            :before-upload="beforeAvatarUpload"
          >
            <img v-if="addpost.post_bg" :src="addpost.post_bg" class="avatar" />
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
          </el-upload>
        </el-form-item>

      //七牛图片上传
      qn: {
        token: '',
        key: ''
      }

上传前先进行文件检查

//上传封面前检查
    async beforeAvatarUpload(file) {
      const isJPG = file.type === 'image/jpeg'
      const isGIF = file.type === 'image/gif'
      const isPNG = file.type === 'image/png'
      const isBMP = file.type === 'image/bmp'

      if (!isJPG && !isGIF && !isPNG && !isBMP) {
        this.$message.error('上传图片必须是JPG/GIF/PNG/BMP 格式!')
        return false
      }
      const isLt2M = file.size / 1024 / 1024 < 2
      if (!isLt2M) {
        this.$message.error('上传头像图片大小不能超过 2MB!')
      }
      //根据文件名生成上传唯一key值
      let key =
        'blog/image/' +
        this.utils.formatDate(new Date().getTime(), 'YY/MM/DD/hh:mm:ss/') +
        file.name
      console.log(key)
      await this.getuploadToken(key)
      return (isJPG || isGIF || isPNG || isBMP) && isLt2M
    }

同时获取token,根据日期时间设置唯一key值

//获取七牛上传token
    getuploadToken: async function(key) {
      const { status, data } = await this.$axios.post('/qiniu/upload', {
        key
      })
      // console.log(status, data)
      if (status == 200 && data.uptoken) {
        this.qn.token = data.uptoken
        this.qn.key = key
        // console.log(this.qn)
      }
    }

上传成功后将返回的key值拼接为真正的url资源路径,并设置到addpost.post_bg上,让img标签正常显示图片

//返回上传的图片地址
    handleAvatarSuccess(res, file) {
      this.addpost.post_bg = 'https://gravatar.catbk.cn/' + res.key
    }

效果大概这样

文章列表
添加文章