① 首先基于element-plus里面的:http-request="upload"自定义封装事件写一个点击事件之后基于腾讯云的
- 登录 对象存储控制台 ,创建存储桶。获取存储桶名称和 地域名称
- 登录 访问管理控制台 ,获取您的项目 SecretId 和 SecretKey。
- 在项目中安装 SDK 【npm i cos-js-sdk-v5 --save】
- 使用 const COS = require('cos-js-sdk-v5');// 或 import COS from 'cos-js-sdk-v5';进行引入
- 前端使用固定密钥计算签名,该格式适用于前端调试,若使用此格式,请避免泄露密钥
【这里还有一些推荐的方法具体见 https://cloud.tencent.com/document/product/436/11459 】
- 当我们获取SecretKey 和 SecretId之后在定义的upload上传方法中调用 cos.uploadFile实现图片上传
腾讯云的相关操作:【https://cloud.tencent.com/document/product/436/11459】
javascript
// 代码:
<template>
<div class="upload-box">
<!-- 给action一个#号 就不会报错了 -->
<!-- file-list是上传的文件列表 可以绑定到上传组件上,让上传组件来显示 -->
<!-- upload组件显示的是file-list -->
<el-upload
class="avatar-uploader"
list-type="picture-card"
:limit="1" action="#"
:before-upload="beforeUpload"
:http-request="upload"
:on-preview="preview"
:file-list="state.fileList"
style="width: 200px"
:on-change="changeFile"
:class="{ disabled: fileComputed }">
<!-- 当fileComputed 的值为 true,则给元素添加名为 "disabled" 的 CSS 类名;如果 fileComputed的值为 false,则移除该 CSS 类名。 -->
</el-upload>
<el-dialog v-model="state.showDialog" title="图片预览">
<img :src="state.imgUrl" alt="" style="width: 100%" />
</el-dialog>
</div>
</template>
<script setup>
import { reactive, computed } from "vue"
import COS from "cos-js-sdk-v5" // 引入腾讯云cos包
import { ElMessage } from "element-plus"
// 实例化COS对象
const cos = new COS({
// 拷贝自己的秘钥和key 只有用自己的key和自己的秘钥才能上传到自己的存储桶里面
SecretId: "自己的身份识别ID", // 身份识别 ID
SecretKey: "自己的身份秘钥", // 身份密钥
})
const state = reactive({
fileList: [],
showDialog: false,
imgUrl: "",
currentFileUid: null, // 记录当前正在上传的uid
})
const fileComputed = computed(() => {
return state.fileList.length === 1
})
// 点击预览事件
const preview = (file) => {
console.log(file.url)
state.imgUrl = file.url
state.showDialog = true
}
const beforeUpload = (file) => {
const types = ["image/jpeg", "image/gif", "image/bmp", "image/png"]
if (!types.some((item) => item === file.type)) {
// 如果不存在
ElMessage.error("上传图片只能是 JPG、GIF、BMP、PNG 格式!")
return false // 上传终止
}
// 检查文件大小 5M 1M = 1024KB 1KB = 1024B
const maxSize = 10 * 1024 * 1024
if (file.size > maxSize) {
// 超过了限制的文件大小
ElMessage.error("上传的图片大小不能大于5M")
return false
}
// 已经确定当前上传的就是当前的这个file了
state.currentFileUid = file.uid
return true // 最后一定要return true
}
// changeFile 函数的主要作用是在文件列表发生变化时,根据最新的文件列表更新 state.fileList,保持数据的同步和一致性。
// 这样可以确保组件在文件变化时能够及时更新展示的内容。如果有任何疑问或需要进一步解释,请随时告诉我!
// 不能用push 这个钩子会执行多次
const changeFile = (file, fileList) => {
// file是当前的文件 fileList是当前的最新数组 state.fileList
// 如果当前fileList中没有该文件的话 就往里进行追加
state.fileList = fileList.map((item) => item)
}
// 进行上传操作
const upload = (params) => {
if (params.file) {
// 执行上传操作
// 这里相当于传入了两个参数 第一个参数包含了上传所需要的参数,第二个参数是一个回调函数用于处理上传操作的结果
// 包括错误信息和上传成功后的返回数据
cos.putObject(
{
Bucket: "存储桶名称", // 存储桶 【自己创建的桶的名称】
Region: "ap-nanjing", // 地域 【自己创建的时候选择的地域】
Key: params.file.name, // 文件名
Body: params.file, // 要上传的文件对象
StorageClass: "STANDARD", // 上传的模式类型 直接默认 标准模式即可
},
(err, data) => {
if (!err && data.statusCode === 200) {
// 上传成功跟新状态中的文件列表
state.fileList = state.fileList.map((item) => {
// 去找谁的uid等于刚刚记录下来的id
if (item.uid === state.currentFileUid) {
// 将成功的地址赋值给原来的url属性
return { url: "http://" + data.Location, upload: true }
}
return item
})
}
}
)
}
}
</script>
<style>
.upload-box {
display: block;
width: 200px;
margin: 0 auto;
}
.disabled .el-upload--picture-card {
display: none;
}
</style>
参考:https://cloud.tencent.com/document/product/436/64960#.E9.AB.98.E7.BA.A7.E4.B8.8A.E4.BC.A0
https://juejin.cn/post/7093678563747954696
注意: 我们在使用cos进行上传的时候需要创建桶,获取秘钥等操作
创建存储桶 【https://cloud.tencent.com/document/product/436/13309 创建存储桶的具体操作】文档中心-左侧创建存储桶
获取秘钥的具体操作 【https://cloud.tencent.com/document/product/598/40488】
-->
补充:
在代码中,如果直接使用 push 方法将文件对象添加到 state.fileList 中,这会导致数组的长度发生变化,
从而触发 Vue 的响应式机制。当触发响应式更新时,changeFile 方法会再次被调用,进而导致多次执行。