前端文件上传金山云

以前公司上传文件都是后端给个请求地址,前端按照后端需要的格式发送请求,后端返回给前端一个服务器可以访问的文件地址,前端再连同其他表单数据进行提交。新公司前端是自己上传金山云直接拿到服务器可以访问的地址(当然上传金山云的签名需要后端返回),再跟其他表单数据请求提交。下面说一下流程

框架:@vue-cli4.5.11

UI库: ant-design-vue1.7.5

相关文档参考:对象存储(KS3)POST Object-金山云

一. 获取签名接口

src/api/common.js

import request from '@/utils/request'

export default class CommonServer {
     
  // 获取金山云上传签名
  static getKsOssSign (params) {
     
    return request({
     
      url: '/ks3/policy/signature',
      method: 'get',
      params
    })
  }
}

二. 自定义文件上传到金山云的名称

src/utils/oss.js

import moment from 'moment' //npm或yarn安装moment

// 文件扩展名提取
export const fileType = fileName => {
     
  return fileName.substring(fileName.lastIndexOf('.') + 1)
}

/**
 * oss路径定义
 * @param file
 * @param customFileType 自定义的扩展名
 */
export const ossPath = (file, customFileType) => {
     
  const folder = moment().format('YYYY-MM-DD')
  const name = moment().format('YYYY-MM-DD-HH-mm-ss-SSS')
  if (file.name) {
     
    const type = fileType(file.name)
    return `项目名称(金山云上创建的对应项目文件名)/upload/${
       folder}/${
       type}/${
       name}.${
       type}`
  } else if (customFileType) {
     
    return `项目名称(金山云上创建的对应项目文件名)/upload/${
       folder}/${
       customFileType}/${
       name}.${
       customFileType}`
  }
}

三. 金山云上传

src/utils/oss.js

import CommonServer from '@/api/common'

/**
 * 金山云上传
 * @returns {Promise}
 */
export const ksOssUpload = (file, customFileType) => {
     
  return new Promise((resolve, reject) => {
     
    const key = ossPath(file, customFileType)
    const params = {
      fileName: key }
    CommonServer.getKsOssSign(params).then(res => {
     
      const {
      accessid, policy, signature, host } = res
      const formData = new FormData()
      formData.append('acl', 'public-read')
      formData.append('key', key)
      formData.append('signature', signature)
      formData.append('KSSAccessKeyId', accessid)
      formData.append('policy', policy)
      formData.append('file', file)
      axios.post(`https://${
       host}`, formData).then(res => {
     
        const {
      status } = res
        if (status === 200) {
     
          const data = {
     
            url: `https://${
       host}/${
       key}`,
            type: file.name ? fileType(file.name) : customFileType
          }
          resolve(data)
        } else {
     
          reject(res)
        }
      }).catch(err => {
     
        reject(err)
      })
    }).catch(err => {
     })
  })
}

四. 其他上传限制判断

src/utils/oss.js

import {
      message } from 'ant-design-vue'

/**
 * 上传文件大小限制
 * @param file
 * @param fileMaxSize
 * @returns {boolean}
 */
export const isMaxFileSize = (file, fileMaxSize = 1) => {
     
  if (!file) return false
  const isMaxSize = file.size / 1024 / 1024 < fileMaxSize
  if (!isMaxSize) {
     
    message.error(`上传文件大小不能超过${
       fileMaxSize}MB!`)
    return false
  }
  return true
}

/**
 * 文件最大数量限制
 * @param fileList
 * @param maxLength
 * @returns {boolean}
 */
export const isMaxFileLength = (fileList = [], maxLength = 3) => {
     
  if (fileList.length >= maxLength) {
     
    message.error(`最多上传${
       maxLength}个文件`)
    return false
  }
  return true
}

/**
 * 判断上传是否为图片
 * @param file
 * @returns {boolean}
 */
export const isImageFile = file => {
     
  if (!file) return false
  const types = [
    'image/png',
    'image/gif',
    'image/jpeg',
    'image/jpg',
    'image/bmp',
    'image/x-icon'
  ]
  const isImage = types.includes(file.type)
  if (!isImage) {
     
    message.error('上传文件非图片格式!')
    return false
  }
  return true
}

/**
 * 判断图片是否损坏
 * @param file
 */
export const isNormalImage = file => {
     
  return new Promise((resolve, reject) => {
     
    if (!file) return
    const image = new Image()
    image.src = file
    image.onload = () => {
     
      resolve({
      status: 1, message: '加载成功' })
    }
    image.onerror = () => {
     
      // eslint-disable-next-line prefer-promise-reject-errors
      reject({
      status: 0, errMsg: '图片损坏,请重新上传' })
    }
  })
}

五. 文件中使用

***.vue, 下面以ant-design-vue上传组件为例,这里只展示上传逻辑

<template>
  ...
  <a-upload v-bind="uploadProps">
      <a-button
        type="primary"
        :loading="loading"
        icon="upload"
      >
        点击上传
      </a-button>
  </a-upload>
  ...
</template>

<script>
  import {
      isMaxFileLength, isMaxFileSize, ksOssUpload } from '@/utils/oss'
  ...
  data () {
     
    return {
     
      uploadProps: {
     
        accept: '*',
        showUploadList: false,
        customRequest: async (param) => {
     
          if (!param.file) return
          if (!isMaxFileLength(this.mediaList, this.maxLength)) return
          if (!isMaxFileSize(param.file, 10)) return
          await this.handleUpload(param.file)
        }
      },
      maxLength:3,
      mediaList: [],
      loading: false
    }
  },
  methods{
     
    ...
    // 上传
    async handleUpload (file) {
     
      try {
     
        this.loading = true
        this.$message.loading('文件上传中')
        const {
      url } = await ksOssUpload(file)  //这里的就是上面src/utils/oss.js里面的上传
        this.mediaList.push(url)
        this.loading = false
        this.$message.success('文件上传成功!')
      } catch (e) {
     
        this.loading = false
        this.$message.destroy()
        this.$message.error(e || '文件上传失败')
      }
    }
  }
  
</script>

你可能感兴趣的:(文件上传,前端开发,javascript,vue.js)