需求:上传图片到腾讯云对象存储,返回图片链接地址。

大概流程:

腾讯云对象存储(Cloud Object Storage,COS)是腾讯云提供的一种存储海量文件的分布式存储服务,用户可通过网络随时存储和查看数据。

COS 使所有用户都能使用具备高扩展性、低成本、可靠和安全的数据存储服务。

COS 通过控制台、API、SDK 和工具等多样化方式简单、快速地接入,实现了海量数据存储和管理。通过 COS 可以进行任意格式文件的上传、下载和管理。

官网文档:https://cloud.tencent.com/document/product/436

使用腾讯云对象存储准备工作:

首先是需要开通腾讯云对象存储服务,然后,登录对象存储控制台,创建存储视频对应的存储桶。配置规则,桶的读写权限,允许的域名等等的,都要进行设置,具体官方文档都有说明,这里就不赘述了。
准备工作结束后,接下来,就是正式使用了:

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)判断文件大小 是否需要分片上传。

// 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'
}// 上传到腾讯云cos
export function uploadObject (file, callback) {/* 1.获取临时秘钥data2.初始化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里的参数Keyconst 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.resultvar credentials = data && data.credentialsif (!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,})},})// 获取上传文件大小let size = file.sizelet key = '/art/' + upload_file_nameif (type === 'video') {// console.log(size / (1024 * 2024))if (size / (1024 * 1024) < 50) {console.log('视频普通上传')cos.putObject({Bucket: config.videoBucket, // 存储桶名称Region: config.Region, // 存储桶所在地域,必须字段Key: key, // 视频名称StorageClass: 'STANDARD',Body: file, // 上传文件对象onHashProgress: (progressData) => {// console.log('校验中', JSON.stringify(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('data', data)if (err) {console.log('err', err)Message({ message: '视频文件上传失败,请重新上传', type: 'error' })} else {let fileUrl = 'https://' + config.videoBucket + '.file.myqcloud.com' + keycallback(fileUrl, origin_file_name) // 返回视频链接地址和视频的原始名称}})} else {console.log('视频分块上传')// 上传分块cos.sliceUploadFile({Bucket: config.videoBucket, // 存储桶名称Region: config.Region, // 存储桶所在地域,必须字段Key: key /* 必须 */,Body: file,onTaskReady: (taskId) => {/* 非必须 */// console.log(taskId)},onHashProgress: (progressData) => {/* 非必须 */// console.log(JSON.stringify(progressData))},onProgress: function (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) => {if (err) {console.log(err)Message({ message: '文件上传失败,请重新上传', type: 'error' })} else {let fileUrl = 'https://' + config.videoBucket + '.file.myqcloud.com' + keycallback(fileUrl, origin_file_name) // 返回视频链接地址和视频的原始名称}})}} else if (type === 'image') {cos.putObject({Bucket: config.imageBucket, // 存储桶名称Region: config.Region, // 存储桶所在地域,必须字段Key: key, // 图片名称StorageClass: 'STANDARD',Body: file, // 上传文件对象onHashProgress: (progressData) => {console.log('校验中', JSON.stringify(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) => {if (data && data.statusCode == 200) {let fileUrl = 'https://' + config.imageBucket + '.file.myqcloud.com' + keycallback(fileUrl) // 返回图片链接地址和视频的原始名称} else {Message({ message: '图片文件上传失败,请重新上传', type: 'error' })}})}})
}export default {uploadObject
}

3、封装图片上传组件、调用上传方法

新建image-upload.vue封装图片上传组件,调用上传方法:

<template><div class="single-image-upload-container"><div class="single-image-upload" :class="{'limit-num': fileList.length>=limit, 'mini': size === 'small'}"><el-upload ref="upload" :file-list="fileList" list-type="picture-card" action="#" :http-request="uploadToCos" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-exceed="exceedTips" :on-success="handeSuccess" :before-upload="beforeImageUpload" :on-change="onChangeHandle"><i class="el-icon-plus"></i><p class="el-upload__tip" slot="tip" v-if="tips">{{tips}}</p><div slot="file" slot-scope="{file}" class="img-con"><img class="el-upload-list__item-thumbnail" :src="file.url" alt=""><span class="el-upload-list__item-actions"><span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)"><i class="el-icon-zoom-in"></i></span><span class="el-upload-list__item-delete" @click="handleRemove(file)"><i class="el-icon-delete"></i></span><span v-if="size === 'small'" style="display:block;marginLeft:0" class="el-upload-list__item-delete" @click="onChangeHandle(file)"><i class="el-icon-edit"></i></span><span v-else class="el-upload-list__item-delete" @click="onChangeHandle(file)"><i class="el-icon-edit"></i></span></span></div></el-upload></div><el-dialog :visible.sync="dialogVisibleShow"><img width="100%" :src="dialogImageUrl" alt=""></el-dialog></div>
</template><script>
import { uploadObject } from '@/utils/upload'
export default {// 上传图片到腾讯云对象存储name: 'ImgUpload',data () {return {imgWidth: 0,imgHeight: 0,picIndex: -1,dialogImageUrl: '',dialogVisibleShow: false,fileList: []}},props: {value: {type: String,default: ''},tips: {type: String,default: ''},size: {type: String,default: 'medium' // small},limit: {type: Number,default: 1},limitSize: {type: Number,default: 10},// 是否校验图片尺寸,默认不校验isCheckPicSize: {type: Boolean,default: false},checkWidth: {type: Number,default: 0 // 图片限制宽度},checkHeight: {type: Number,default: 0 // 图片限制高度},topLimitWidth: {type: Number,default: 0 // 图片限制宽度上限(有时需要校验上传图片宽度在一个范围内)},topLimitHeight: {type: Number,default: 0 // 图片限制高度上限(有时需要校验上传图片高度在一个范围内)},busiType: {type: Number,default: 2},index: {type: Number,default: -1 // 当前图片index,限制可以上传多张时,针对某一张进行操作,需要知道当前的index},limitType: {type: String,default: '' // gif,webp/gif/webp(限制上传格式)}},components: {},created () {if (this.value) {this.fileList = [{ url: this.value }]}},watch: {value (val) {if (val) {this.fileList = [{ url: val }]} else {this.fileList = []}}},methods: {onChangeHandle (file, fileList) {this.fileList = [file]// console.log('onChangeHandle file, fileList', file, fileList);this.$refs.upload.$refs['upload-inner'].handleClick()},handleRemove (file, fileList) {// console.log('handleRemove file, fileList', file, fileList);this.$emit('input', '')this.fileList = fileList},handlePictureCardPreview (file) {this.dialogImageUrl = file.urlthis.dialogVisibleShow = true},beforeImageUpload (file) {// console.log('beforeImageUpload', file);const imgType = file.typeconst isLtSize = file.size / 1024 / 1024 < this.limitSizeconst TYPE_NOGIFWEBP = ['image/png', 'image/jpeg', 'image/jpg']const TYPE_NOGIF = ['image/png', 'image/jpeg', 'image/jpg', 'image/webp']const TYPE_NOWEBP = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif']const TYPE_ALL = ['image/png', 'image/jpeg', 'image/jpg', 'image/gif', 'image/webp']let isType = trueif (this.limitType && this.limitType.indexOf('gif') !== -1 && this.limitType.indexOf('webp') !== -1) {if (TYPE_NOGIFWEBP.indexOf(imgType) === -1) {isType = falsethis.$message.error('仅支持上传 jpg、png、jpeg、gif、webp 格式的图片!')}} else if (this.limitType && this.limitType.indexOf('gif') === -1 && this.limitType.indexOf('webp') === -1) {if (TYPE_NOGIFWEBP.indexOf(imgType) === -1) {isType = falsethis.$message.error('仅支持上传 jpg、png、jpeg 格式的图片!')}} else if (this.limitType && this.limitType.indexOf('webp') !== -1) {if (TYPE_NOGIF.indexOf(imgType) === -1) {isType = falsethis.$message.error('仅支持上传 jpg、png、jpeg、webp 格式的图片!')}} else if (this.limitType && this.limitType.indexOf('gif') !== -1) {if (TYPE_NOWEBP.indexOf(imgType) === -1) {isType = falsethis.$message.error('仅支持上传 jpg、png、jpeg、gif 格式的图片!')}} else {if (TYPE_ALL.indexOf(imgType) === -1) {isType = falsethis.$message.error('仅支持上传 jpg、png、jpeg、webp、gif 格式的图片!')}}if (!isLtSize) {this.$message.error(`上传图片大小不能超过${this.limitSize}MB!`)}if (this.isCheckPicSize === true) {const width = this.checkWidthconst height = this.checkHeightconst topWidth = this.topLimitWidthconst topHeight = this.topLimitHeightconst that = thisconst isSize = new Promise((resolve, reject) => {// console.log('Promise')// window对象,将blob或file读取成一个urlconst _URL = window.URL || window.webkitURLconst img = new Image()img.onload = () => { // image对象的onload事件,当图片加载完成后执行的函数// console.log('img.onload')that.imgWidth = img.widththat.imgHeight = img.heightif (width && height) { // 校验图片的宽度和高度let valid = falseif (topWidth && topHeight) {// 校验图片宽度和高度范围valid = ((width <= img.width) && (img.width <= topWidth)) && ((height <= img.height) && (img.height <= topHeight))} else if (topHeight) {// 校验图片高度范围valid = img.width === width && ((height <= img.height) && (img.height <= topHeight))} else if (topWidth) {// 校验图片宽度范围valid = ((width <= img.width) && (img.width <= topWidth)) && img.height === height} else {// 校验图片宽度、高度固定值valid = img.width === width && height === img.height}valid ? resolve() : reject(new Error('error'))} else if (width) { // 只校验图片的宽度let valid = falseif (topWidth) {// 校验图片宽度范围valid = (width <= img.width) && (img.width <= topWidth)} else {// 校验图片宽度固定值valid = img.width === width}valid ? resolve() : reject(new Error('error'))} if (height) { // 只校验图片的高度let valid = falseif (topHeight) {// 校验图片高度范围valid = (height <= img.height) && (img.height <= topHeight)} else {// 校验图片高度固定值valid = img.height === height}valid ? resolve() : reject(new Error('error'))}}img.src = _URL.createObjectURL(file)}).then(() => {// console.log('then')return file}, () => {// console.log('reject')let text = ''if (width && height) {if (topWidth && topHeight) {text = `图片尺寸限制为:宽度${width}~${topWidth}px,高度${height}~${topHeight}px!`} else if (topHeight) {text = `图片尺寸限制为:宽度${width}px,高度${height}~${topHeight}px!`} else if (topWidth) {text = `图片尺寸限制为:宽度${width}~${topWidth}px,高度${height}px!`} else {text = `图片尺寸限制为:宽度${width}px,高度${height}px!`}} else if (width) {if (topWidth) {text = `图片尺寸限制为:宽度${width}~${topWidth}px!`} else {text = `图片尺寸限制为:宽度${width}px!`}} else if (height) {if (topHeight) {text = `图片尺寸限制为:高度${height}~${topHeight}px!`} else {text = `图片尺寸限制为:高度${height}px!`}}this.$message.error(text)return Promise.reject(new Error('error'))})return isType && isLtSize && isSize} else {// window对象,将blob或file读取成一个urlconst _URL = window.URL || window.webkitURLconst img = new Image()img.onload = () => { // image对象的onload事件,当图片加载完成后执行的函数this.imgWidth = img.widththis.imgHeight = img.height}img.src = _URL.createObjectURL(file)return isType && isLtSize}},// 上传文件uploadToCos () {// console.log('uploadToCos uploadFile', this.fileList)let files = uploadObject(this.fileList[0].raw, (url) => {this.$emit('input', url)})},exceedTips (file, fileList) {this.$message(`最多上传${fileList.length}个文件!`)},handeSuccess (res, file, fileList) {console.log('handeSuccess')}}
}
</script><style lang='less'>
@small-size: 80px;
.single-image-upload&&.limit-num {.el-upload--picture-card {display: none !important;}
}
.single-image-upload&&.mini {.el-upload {border: 1px dashed #d9d9d9;border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;}.el-upload-list__item {width: @small-size;height: @small-size;text-align: center;/*去除upload组件过渡效果*/transition: none !important;}.el-upload--picture-card {width: @small-size;height: @small-size;line-height: @small-size;text-align: center;}
}
.el-upload-list__item&&.is-success {.img-con {width: 100%;height: 100%;}
}
</style>

action:上传地址,必填,但我们使用http-request,填任意字符串即可,没有实际意义。

http-request:覆盖默认上传行为,我们这里就需要自定义上传行为。

4、页面使用组件

<template><div>    <img-upload v-model="img" :size="'small'" :tips="'建议图片宽度为350,比例为4:3 / 3:4 / 1:1 JPG、JPGE、PNG 小于5M,仅限上传一张'" :limit="1" :limitSize="5"></img-upload></div>
</template>
<script>
import ImgUpload from '@/components/image-upload'export default {name: 'add',components: {ImgUpload},data () {return {img: ''     }    },props: {},watch: {},created () {    },mounted () {},methods: {    }
}
</script>

上传过程中打印进度信息:

vue 上传图片到腾讯云对象存储相关推荐

  1. php上传图片(腾讯云对象存储)

    public function cosPub(){ //引入腾讯云的文件 autoload.php'$secretId = ""; //"云 API 密钥 SecretI ...

  2. vue使用腾讯云对象存储碰到的坑

    为了开法方法,小程序,公众号和前端使用相同接口,使用了vue作后台. 1:cos-nodejs-sdk-v5所需要环境版本不一致 为项目添加腾讯云对象存储时,安装sdk依赖: npm i cos-no ...

  3. Android腾讯云对象存储上传图片

    最近使用腾讯云对象存储,项目比较赶,想找个现有的复制结果找了半天,全是官方文档,最后乖乖的自己写了,记录一下以后用的时候方便. 腾讯云对象存储官方文档地址:https://cloud.tencent. ...

  4. 腾讯云cos html,腾讯云对象存储(COS)插件安装设置图文教程

    腾讯云对象存储(COS)插件是腾讯云官方开发的针对在 wordpress中使用腾讯云对象存储cos的用户开发的辅助插件.通过在 wordpress程序中安装插件的方式,很方便的把WordPress静态 ...

  5. 硅谷课堂 06_整合腾讯云对象存储和课程分类管理

    硅谷课堂第六天-整合腾讯云对象存储和课程分类管理 文章目录 硅谷课堂第六天-整合腾讯云对象存储和课程分类管理 一.讲师管理模块整合腾讯云对象存储 1.腾讯云对象存储介绍 1.1.开通"对象存 ...

  6. 腾讯云cos html,Docsify+腾讯云对象存储 COS,一键搭建云上静态博客

    最近一直在想如何利用 COS 简化静态博客的搭建过程.搜了很多的静态博客搭建过程,发现大部分的静态博客都要通过编译才能生成静态页面.功夫不负有心人,终于让我找到了一个超简洁博客的搭建方法. 效果预览 ...

  7. 硅谷课堂第五课-腾讯云对象存储和课程分类管理

    硅谷课堂第六天-整合腾讯云对象存储和课程分类管理 文章目录 硅谷课堂第六天-整合腾讯云对象存储和课程分类管理 一.讲师管理模块整合腾讯云对象存储 1.腾讯云对象存储介绍 1.1.开通"对象存 ...

  8. 腾讯云对象存储COS + 数据万象CI = 完善的图片解决方案

    沈唁 PHP工程师,开源爱好者,WordPress插件Sync QCloud COS 作者,GitHub@sy-records 在日常开发当中,我们必然会遇到一些图片存储问题,例如用户头像.聊天产生的 ...

  9. 腾讯云对象存储 python_python 云存储

    广告关闭 云服务器1核2G首年99年,还有多款热门云产品满足您的上云需求 存储桶 bucketxml python sdk 存储桶名称由两部分组成:用户自定义字符串 和 appid,两者以中划线&qu ...

最新文章

  1. c枚举类型enum例题_C语言--enum,typedef enum 枚举类型详解
  2. python pandas读取excel-python pandas模块简单使用(读取excel为例)
  3. 必会重构技巧(三):提取接口
  4. 第7章:MapReduce编程
  5. log4j的配置方法
  6. ResNet、Faster RCNN、Mask RCNN 是专利算法吗?盘点何恺明参与发明的专利!
  7. Google广告优化与工具
  8. C# this关键字(给底层类库扩展成员方法)
  9. ODBC操作excel
  10. svn恢复误删文件步骤
  11. 中国电信物联网平台入门学习笔记6:电信平台数据模拟采集
  12. linux环境下如何重装系统,详细教你linux电脑系统怎么安装
  13. 【调剂】 济南大学机器学习及其应用课题组拟接收计算机硕士(调剂及第一志愿)报考-预宣传...
  14. 算法第二章上机实践报告
  15. Android图片缓存框架 - Fresco的GenericDraweeHierarchy (五)
  16. Unity 入门教程:贪吃射(1) —— Unity 安装和项目创建
  17. 正序,负序,零序分量的产生与计算
  18. Python 标准库之 shutil 高阶文件操作『详细』
  19. 推荐十个最好的Java性能故障排除工具:
  20. cad怎么画坐标系箭头_如何方便快捷地用CAD画箭头

热门文章

  1. (一)算法基础——枚举
  2. 【个人UNITY笔记】{基础} 2D游戏中使用Shader或Camera解决Sprite前后遮挡关系
  3. 服务器电源故障日志信息,服务器故障重启日志
  4. css样式学习笔记一
  5. 瑞幸咖啡为何能逆风翻盘?
  6. 使用WinDBG调试查看C#内存转储文件
  7. round()函数在Java和MySQL中的使用
  8. (天高云淡)墨渊第六版引导页源码 彩虹云任务引导页源码
  9. python小游戏制作软件_Python制作打地鼠小游戏
  10. 6阶幻方C语言,6阶幻方解法图