使用iView的Upload組件實現(xiàn)將文件上傳至OSS文件服務(wù)器

一、情景摘要

在項目開發(fā)中,我們經(jīng)常會遇到需要上傳附件的需求,如果實際業(yè)務(wù)場景下只需要上傳少量附件的,上傳到代碼部署的同一臺服務(wù)器是沒問題的,但是如果上傳附件的場景非常多,那么同一臺服務(wù)器可能就承受不住了,這時就需要一臺專門的文件服務(wù)器。我們常用的是阿里云的對象存儲OSS。根據(jù)阿里云的OSS官方文檔介紹(參見:https://help.aliyun.com/document_detail/31927.html?spm=a2c4g.11186623.2.17.3fc872c1lzmOdb#concept-qp2-g4y-5db
),有多種方式的直傳方式,本文選取了安全和性能就都比較高的服務(wù)端簽名直傳并設(shè)置上傳回調(diào)的方式,重點講述前端實現(xiàn)。

二、操作流程

1、前端根據(jù)后端提供的接口向后端發(fā)送請求,獲取文件上傳需要的簽名、Policy和回調(diào)等信息。

// 請求api封裝
const baseApi = process.env.NODE_ENV === 'production' ? '/' : '/upload'
import $axios from '@/libs/request'
// 請求方法
export const getSignature = () => {
  // $axios.request()為封裝過的專門發(fā)送請求的方法
  return $axios.request({
    url: `${baseApi}/upload/token`,
    method: 'GET'
  })
}

2、根據(jù)請求獲取到的簽名策略信息生成oss上傳需要的表單參數(shù)

import {getSignature} from '@/api/api-upload'

let accessid = ''
let policyBase64 = ''
let signature = ''
let callbackbody = ''
let key = ''
let expire = 0
let host = ''
let g_object_name = ''
let now =  Date.parse(new Date()) / 1000;

// 生成隨機字符串
function random_string(len) {
  len = len || 32;
  var chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  var maxPos = chars.length;
  var pwd = '';
  for (let i = 0; i < len; i++) {
    pwd += chars.charAt(Math.floor(Math.random() * maxPos));
  }
  return pwd;
}
// 獲取用戶上傳原始文件名
function get_file_name(filename) {
  let pos = filename.lastIndexOf('.')
  let suffix = ''
  if (pos != -1) {
    suffix = filename.substring(pos)
  }
  return suffix;
}
//  把隨機生成的字符串拼接在原始上傳文件名后面生成新的唯一文件名
function set_file_name(filename) {
  let suffix = get_file_name(filename)
  g_object_name = key + random_string(10) + suffix
  return ''
}

// 獲取后端返回的簽名信息,生成oss參數(shù)
function oss(filename = null) {
  // 可以判斷當(dāng)前expire是否超過了當(dāng)前時間, 如果超過了當(dāng)前時間, 就重新取一下, 3 s 作為緩沖。
  now = Date.parse(new Date()) / 1000;
  if (expire < now + 3) {
    // 調(diào)用后端服務(wù)器接口獲取簽名信息,利用axios返回promise,可以鏈?zhǔn)秸{(diào)用
      return getSignature().then(res => {
        console.log(res)
        /* 返回的簽名策略信息包含:
        {
          accessid: "LTAI*******UPPr", // 用戶請求的accessid
          callback: "eyJjYWxs************H0ifQ==", // 回調(diào)
          dir: "test/file-dir/", // 上傳文件的存儲位置
          expire: "1557974779", // 上傳策略Policy失效時間
          host: "http://xxxxxxxxx.com", // 上傳文件服務(wù)器地址
          policy: "eyJleHBp***********6/EMG7U=" ,// 用戶表單上傳的策略(Policy)
          signature: "JumJy*****k6/EMG7U=" // 簽名信息
        }
        */
        policyBase64 = res['policy']
        accessid = res['accessid']
        signature = res['signature']
        expire = parseInt(res['expire'])
        callbackbody = res['callback']
        host = res['host']
        key = res['dir']

        if (filename != null) {
          set_file_name(filename)
        }
        // 返回表單上傳需要的參數(shù)信息
        return {
          'host': host,
          'key': g_object_name,
          'policy': policyBase64,
          'OSSAccessKeyId': accessid,
          'success_action_status': '200', //讓服務(wù)端返回200,不然,默認(rèn)會返回204
          'callback': callbackbody,
          'signature': signature,
        };
      })
  }
}

export { oss }

3、配合iView的Upload組件實現(xiàn)上傳

生成上傳的表單參數(shù)后,使用任何文件上傳的組件都可以,只需要在提交文件上傳的時候帶上生成的參數(shù)即可。這里我們在vue項目中使用iView的Upload組件進行上傳。

<Upload
  multiple
  type="drag"
  :action="uploadHost" // 上傳地址
  :data='uploadData' // 上傳攜帶的參數(shù)
  :before-upload='beforeUpload' // 上傳的鉤子
  :on-success="handleSuccess" // 上傳成功后回調(diào)
  >
  <div style="padding: 20px 0" class="handle_upload">
    <img src="../../../assets/img/business/upload.png">
    <span class="des">點擊將文件拖拽或點擊上傳</span>
  </div>
</Upload>
// 引入生成上傳參數(shù)方法
import {oss} from '@/libs/uploadFile'
export default{
  data() {
  // 附件上傳路徑
    uploadHost: '',
    // 附件上傳攜帶參數(shù)
    uploadData: {},
    // 上傳后返回的存儲的文件名
    fileName: '',
    // 上傳后返回的文件存儲地址
    filePath: ''
  },
  methods: {
    // 在Upload組件的鉤子before-upload中獲取到生成的參數(shù)信息
    beforeUpload(file) {
      return oss(file.name).then(res => {
        this.uploadHost = res.host
        this.uploadData = res
      })
    },
    // 上傳成功的回調(diào)函數(shù)
    handleSuccess(res, file, fileList) {
      console.log(res.data)
      /* 上傳成功后,文件服務(wù)器會返回上傳文件在oss上存儲位置、文件名及相關(guān)信息
      {
        filename: "test/file-dir/JdzYDhdrtF.jpg"
        height: "683"
        mimeType: "image/jpeg"
        size: "186142"
        url: "http://xxxx.xxx.com/test/file-dir/JdzYDhdrtF.jpg"
        width: "1024"
      }
     *
    */

    // 根據(jù)自己的業(yè)務(wù)場景,將返回的文件位置信息和其他表單信息一起提交給后端進行業(yè)務(wù)關(guān)聯(lián),在其他地方需要使用附件時可以根據(jù)url位置找到上傳的文件 
      this.fileName: res.data.filename,
      this.filePath: res.data.url
    }
  }
}

至此,一個完整功能的文件上傳到阿里云的OSS已經(jīng)完成。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容