场景:

使用elementUI框架 直接在页面就将本地文件上传至七牛云后返回图片地址


首先是上传模板

singleUpload.vue

目录: src/components/upload/singleUpload.vue

有两个需要改的直接搜

qiniu.region.z1 -> 改成自己七牛云配置的region

qiniu.region.z0: 代表华东区域
qiniu.region.z1: 代表华北区域
qiniu.region.z2: 代表华南区域
qiniu.region.na0: 代表北美区域
qiniu.region.as0: 代表新加坡区域

http://qinniuyun.source.com -> 改成自己七牛云的资源地址

<template>
  <div class="singleImageUpload3 upload-container">
    <el-upload
      v-show="!imageUrl"
      element-loading-text="正在上传~"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.8)"
      :multiple="false"
      :show-file-list="false"
      :before-upload="beforeUpload"
      class="image-uploader"
      drag
      action="http://upload.qiniu.com"
    >
      <i class="el-icon-upload" />
      <div class="el-upload__text">
        <em>点击上传</em>
      </div>
    </el-upload>
    <div v-show="imageUrl" class="image-preview">
      <div class="image-preview-wrapper">
        <img :src="imageUrl">
        <div class="image-preview-action">
          <i class="el-icon-delete" @click="rmImage" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { policy } from '@/api/qiniu'
import * as qiniu from 'qiniu-js'
import * as day from 'dayjs'

export default {
  name: 'SingleUpload',
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      tempUrl: '',
      dataObj: { token: '', key: '' }
    }
  },
  computed: {
    imageUrl() {
      return this.value
    }
  },
  methods: {
    rmImage() {
      this.emitInput('')
    },
    emitInput(val) {
      this.$emit('input', val)
    },
    getUUID() {
      // eslint-disable-next-line no-bitwise
      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => (c === 'x' ? (Math.random() * 16 | 0) : ('r&0x3' | '0x8')).toString(16))
    },
    beforeUpload(file) {
      const _self = this
      _self.fileName = file.name.substr(file.name.lastIndexOf('.'))
      return new Promise((resolve, reject) => {
        policy().then(response => {
          _self.token = response.data
          _self.upQiniu(file)
          console.log(_self.token)
        }).catch(() => {
          reject(false)
        })
      })
    },
    upQiniu(e) {
      console.log('开始上传',e)
      const _self = this
      _self.loading = true
      const file = e // Blob 对象,上传的文件
      const config = {
        useCdnDomain: true,
        region: qiniu.region.z1
      }
      const key = `${day().format('YYYYMMDD')}/${_self.getUUID()}${_self.fileName}`
      const putExtra = {
        fname: e.name,
        params: {},
        mimeType: null // 用来限制上传文件类型,为 null 时表示不对文件类型限制;限制类型放到数组里: ["image/png", "image/jpeg", "image/gif"]
      }
      const observable = qiniu.upload(file, key, _self.token, putExtra, config)
      observable.subscribe({
        next: result => {
          // 主要用来展示进度
        },
        error: errResult => {
          // 失败报错信息
          console.log(errResult)
        },
        complete: result => {
          // 接收成功后返回的信息
          const url = `${'http://qinniuyun.source.com/'}${result.key}`
          console.log('图片地址',url)
          _self.loading = false
          _self.emitInput(url)
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
@import "~@/styles/mixin.scss";
.upload-container {
  width: 100%;
  position: relative;
  .image-uploader {
    width:200px;
    float: left;
  }
  .image-preview {
    width: 200px;
    height: 200px;
    position: relative;
    float: left;
    margin-left: 50px;
    .image-preview-wrapper {
      position: relative;
      width: 100%;
      height: 100%;
      img {
        width: auto;
        height: 100%;
      }
    }
    .image-preview-action {
      position: absolute;
      width: 100%;
      height: 100%;
      left: 0;
      top: 0;
      cursor: default;
      text-align: center;
      color: #fff;
      opacity: 0;
      font-size: 20px;
      background-color: rgba(0, 0, 0, .5);
      transition: opacity .3s;
      cursor: pointer;
      text-align: center;
      line-height: 200px;
      .el-icon-delete {
        font-size: 36px;
      }
    }
    &:hover {
      .image-preview-action {
        opacity: 1;
      }
    }
  }
}
</style>

mixin.scss

目录: src/styles/mixin.scss

@mixin action-bar {
  .action-bar {
    height: 33px;
    background: #f2fafb;
    padding: 0 15px;
    box-sizing: border-box;
  
    .bar-btn {
      display: inline-block;
      padding: 0 6px;
      line-height: 32px;
      color: #8285f5;
      cursor: pointer;
      font-size: 14px;
      user-select: none;
      & i {
        font-size: 20px;
      }
      &:hover {
        color: #4348d4;
      }
    }
    .bar-btn + .bar-btn {
      margin-left: 8px;
    }
    .delete-btn {
      color: #f56c6c;
      &:hover {
        color: #ea0b30;
      }
    }
  }
}

index.js

获取七牛云token , 自己改成自家调用请求的封装

目录: src/api/qiniu/index.js

// 获取token

import request from "@/utils/request";

export function policy() {
    return request({
        url: '/api/token',
        method: 'get'
    })
}

index.vue

使用,如在表单的某个字段是图片

<el-form-item label="照片" prop="photo">
  <single-upload v-model="form.photo" />
</el-form-item>

需要在下面引入,即可

<script>
import singleUpload from '@/components/upload/singleUpload'

export default {
  components: { singleUpload },
  data() {
  ...
Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐