vue 上传图片到腾讯云对象存储
之前总结过 vue
封装图片上传组件到腾讯云对象存储,后来又加了一些功能,在图片过大时进行压缩,压缩完成之后,再上传到腾讯云对象存储;并且,对上传方法进行了优化,所以重新记录一下。
1、 引入cos-js-sdk-v5
安装 JavaScript SDK
:
npm install cos-js-sdk-v5
安装成功后会有如下信息:
2、封装uploadcos.js
新建文件uploadcos.js
,封装上传文件方法。
/**
* 本文件为腾讯云对象存储相关工具类方法
注意:桶的访问权限需要设置指定域名(不然会出现跨域问题),现在设置允许访问的域名是:
http://localhost:8080 https://xxx.com.cn/
所以本地调试时,需要用http://localhost:8080,不可用其他端口。
跨域配置:
桶:指定域名 + 指定子账号能上传;外部不能访问,统一通过cdn访问;
CDN:设置为无跨域限制
---- COD自主诊断工具:https://cloud.tencent.com/login?s_url=https%3A%2F%2Fconsole.cloud.tencent.com%2Fcos5%2Fdiagnose -----
*/
// https://cloud.tencent.com/document/product/436/11459
import COS from 'cos-js-sdk-v5'
import {
Message } from 'element-ui'
import {
getCOSSecretKey } from '@/api/index'
// 存储桶所在地域
const BUCKET_REGION = 'ap-beijing'
// 使用分片上传阈值10(M)
const SLICE_SIZE = 10
const BUCKET_TYPE_CONFIG = {
video: 'video-b-123456',
image: 'image-b-123456',
file: 'file-b-123456'
}
const BUCKET_DOMAIN = {
video: 'https://abcd-video.xxx.com.cn',
image: 'https://abcd-image.xxx.com.cn'
}
const FOLDER_PATH_NAME = {
// 内容图片
ART: {
prod: '/art/',
test: '/test/art/'
},
// 日常活动图片
ACT: {
prod: '/act/',
test: '/test/act/'
},
// 产品图片
WARE: {
prod: '/ware/',
test: '/test/ware/'
},
// 广告&宣传图片
ADV: {
prod: '/adv/',
test: '/test/adv/'
}
}
/**
* options @param {Object}
* sliceSize:使用切片上传阈值 默认10(M)
* bucketType:桶类型 video,image,file 三种类型
* busiType:业务类型
* needLaoding:是否需要loading遮罩层
* bucketEnv:桶的环境 测试、生产
* bucketName:桶的名称
* bucketDomain:桶的域名 用来拼接key
* bucketPrefix:自定义桶地址前缀片段
* credentials:后台返回凭证信息
* keyBackData:后台返回密钥信息 为credentials父级
*/
class Cos {
constructor(options) {
this.bucketEnv =
window.msBaseUrl === 'https://xxx.com.cn/' ? 'prod' : 'test'
this.bucketType = options?.bucketType || BUCKET_TYPE_CONFIG.file
this.bucketName = BUCKET_TYPE_CONFIG[this.bucketType]
this.bucketDomain = BUCKET_DOMAIN[this.bucketType]
this.sliceSize = options?.sliceSize || SLICE_SIZE
this.busiType = options?.busiType || 'ART'
this.bucketPrefix = FOLDER_PATH_NAME[this.busiType][this.bucketEnv]
this.credentials = null
this.keyBackData = null
}
/**
* 获取密钥
* @returns Object
*/
async getKey () {
try {
const res = await getCOSSecretKey({
bucket: this.bucketName
})
if (
res?.result?.credentials &&
Object.keys(res?.result?.credentials).length
) {
this.keyBackData = res.result
this.credentials = res.result.credentials
return this.credentials
}
return null
} catch (error) {
return null
}
}
/**
* 生成上传资源名称 6位随机数+uid+文件名
*/
generateKey (file) {
const timeStamp = file.uid ? file.uid : new Date().getTime() + ''
const suffix = file.name.split('.')[file.name.split('.').length - 1]
return `${
this.randomString()}_${
timeStamp}.${
suffix}`
}
/**
* 获取随机数
* @param {*} len
* @returns
*/
randomString (len = 6) {
const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789'
const maxPos = chars.length
let res = ''
for (let i = 0; i < len; i++) {
res += chars.charAt(Math.floor(Math.random() * maxPos))
}
return res
}
/**
* 创建COS对象实例
* @returns Object
*/
async getCosInstance () {
const getKey = await this.getKey()
if (getKey) {
const {
tmpSecretId, tmpSecretKey, sessionToken } = this.credentials
const {
startTime, expiredTime } = this.keyBackData
const params = {
TmpSecretId: tmpSecretId,
TmpSecretKey: tmpSecretKey,
SecurityToken: sessionToken,
StartTime: startTime,
ExpiredTime: expiredTime
}
const _cos = new COS({
getAuthorization: function (options, callback) {
callback(params)
}
})
return _cos
}
return null
}
/**
* 单个文件上传到腾讯云cos
* @param {*} file
* @returns
*/
async uploadHandle (file) {
const cos = await this.getCosInstance()
if (cos) {
const KEY = `${
this.bucketPrefix}${
this.generateKey(
file
)}`
console.log('KEY', KEY)
return new Promise((resolve, reject) => {
// if (this.needLoading) {
// var loadingInstance = Loading.service({ fullscreen: true })
// }
cos.uploadFile(
{
Bucket: this.bucketName /* 填入您自己的存储桶,必须字段 */,
Region: BUCKET_REGION /* 存储桶所在地域,例如ap-beijing,必须字段 */,
Key: KEY /* 存储在桶里的对象键(例如1.jpg,a/b/test.txt),必须字段 */,
Body: file /* 必须,上传文件对象,可以是input[type="file"]标签选择本地文件后得到的file对象 */,
SliceSize:
1024 *
1024 *
this
.sliceSize /* 触发分块上传的阈值,超过5MB使用分块上传,非必须 */,
onTaskReady: function (taskId) {
/* 非必须 */
// console.log(taskId)
},
onProgress: function (progressData) {
/* 非必须 */
// console.log(JSON.stringify(progressData))
const percent = parseInt(progressData.percent * 10000) / 100
const speed =
parseInt((progressData.speed / 1024 / 1024) * 100) / 100
console.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;')
},
onFileFinish: function (err, data, options) {
/* 非必须 */
console.log(options.Key + '上传' + (err ? '失败' : '完成'))
}
},
(err, data) => {
// loadingInstance && loadingInstance.close()
if (err) {
Message.error(err)
reject(err)
}
const url = `${
this.bucketDomain}${
KEY