官网文档链接:https://cloud.tencent.com/document/product/436/6268
需求
项目里之前上传视频是调后端接口,接口将视频保存到服务器,然后返回视频链接。
后来,后端说是很占用带宽,所以想进行一个改版,让前端直接保存到腾讯云对象存储,上传成功后拿到视频链接地址,这样就不用经过后端了。
项目是web端上传,在此,记录一下具体实现过程。
前期工作
当然,首先是需要开通腾讯云对象存储服务,然后,登录对象存储控制台,创建存储视频对应的存储桶。
配置规则,桶的读写权限,允许的域名等等的,都要进行设置,具体官方文档都有说明,这里就不赘述了。
主要是记录一下视频上传和获取视频第一帧。
1、 引入cos-js-sdk-v5
安装 JavaScript SDK
:
npm install cos-js-sdk-v5
按照成功后会有如下信息:
2、封装upload.js
新建文件upload.js
,封装上传文件方法,判断上传文件为视频还是图片,视频上传到视频对应的桶,图片上传到图片对应的桶,视频如果大于50M,则分片上传。
步骤:
1)getCOSSecretKey
方法调用获取临时秘钥data;
由于固定密钥放在前端会有安全风险,所以使用临时密钥的方式:前端首先请求服务端,服务端使用固定密钥调用 STS 服务申请临时密钥,然后返回临时密钥到前端使用。
2)初始化;
3)判断上传文件的类型;
4)判断文件大小 是否需要分片上传。
/**
readme:
本文件为腾讯云对象存储相关工具类方法
方法一:getCOSList 查询腾讯云对象存储指定桶中的文件
方法二:uploadObject 上传文件到腾讯云对象存储的指定桶
方法三:removeObject 删除腾讯云对象存储指定桶中的文件
注意:桶的访问权限需要设置指定域名(不然会出现跨域问题),现在设置允许访问的域名是:
http://localhost:8080 https://xxx.com.cn/
所以本地调试时,需要用http://localhost:8080,不可用其他端口。
跨域配置:
桶:指定域名 + 指定子账号能上传;外部不能访问,统一通过cdn访问;
CDN:设置为无跨域限制
*/
// https://cloud.tencent.com/document/product/436/11459
import COS from 'cos-js-sdk-v5'
import {
Message } from 'element-ui'
import {
getCOSSecretKey } from '@/api/common/index'
const config = {
videoBucket: 'xxx',
imageBucket: 'xxx',
Region: 'ap-beijing'
}
/**
文件上传到文件夹规则:商城文章素材上传到 art 文件夹
图片上传到图片桶(imageBucket):
生产环境文件夹:imageBucket + '/art/'
测试环境文件夹:imageBucket + '/test/art/'
视频上传到视频桶(videoBucket):
生产环境文件夹:videoBucket + '/art/'
测试环境文件夹:videoBucket + '/test/art/'
*/
export function getCOSList (callback) {
let type = 'video'
getCOSSecretKey({
bucket: type === 'video' ? config.videoBucket : config.imageBucket }).then(response => {
// 后台接口返回 密钥相关信息
// 后台接口返回 密钥相关信息
const data = response.result
var credentials = data && data.credentials
if (!data || !credentials) return console.error('credentials invalid')
// 初始化
var cos = new COS({
getAuthorization: (options, callback) => {
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
StartTime: data.startTime,
ExpiredTime: data.expiredTime,
expiration: data.expiration,
requestId: data.requestId,
})
},
})
cos.getBucket(
{
Bucket: type === 'video' ? config.videoBucket : config.imageBucket, // 存储桶名称
Region: config.Region, // 存储桶所在地域,必须字段
// Prefix: 'a/', /* 列出目录 a 的所有文件,非必须 */
onHashProgress: (progressData) => {
},
onProgress: (progressData) => {
const percent = parseInt(progressData.percent * 10000) / 100;
const speed = parseInt((progressData.speed / 1024 / 1024) * 100) / 100;
// console.log('进度:' + percent + '%; 速度:' + speed + 'Mb/s;');
},
},
(err, data) => {
console.log('err', err)
if (err) {
Message({
message: '列表获取失败!', type: 'error' })
} else {
console.log('列表data', data)
}
}
)
})
}
// 上传到腾讯云cos
export function uploadObject (file, callback) {
console.log('file, flag', file)
// return
/* 1.获取临时秘钥data
2.初始化
3.判断上传文件的类型
4.判断文件大小 是否需要分片上传*/
const type = file.type.substring(0, 5)
let fileName = file.name || ""
const origin_file_name = fileName.split(".").slice(0, fileName.split(".").length - 1).join('.') // 获取文件名称
// console.log('origin_file_name', origin_file_name)
// 获取当前时间戳 与文件类型拼接 为cos.putObject里的参数Key
const upload_file_name = new Date().getTime() + '.' + fileName.split(".")[fileName.split(".").length - 1] // 文件上传名称定义为当前时间戳
// console.log('upload_file_name', upload_file_name)
// 获取密钥
getCOSSecretKey({
bucket: type === 'video' ? config.videoBucket : config.imageBucket })
.then(response => {
// 后台接口返回 密钥相关信息
const data = response.result
var credentials = data && data.credentials
if (!data || !credentials) return console.error('credentials invalid')
// 初始化
var cos = new COS({
getAuthorization: (options