1.需求:将文件上传至腾讯云私有数据库
步骤:
- 安装腾讯云sdk(现在是cos-js-sdk-v5)
- 获取临时身份凭证token,该token被设置为1小时有效
- 拿到临时身份凭证后上传文件
- 将上传后的文件id或者url(看后端需要什么数据)传给后端,在数据库中保存
- 由于是私有库,需要对显示的文件在下载的时候去获取真正的文件地址(如果是共有库,这一步省略)
2.上传至腾讯云
// html 代码
<el-upload
action
:http-request="getSignToken"
:data="fileType"
:on-change="change"
:before-upload="beforeUpload"
:on-remove="handleRemove"
multiple
:limit="element.options.length"
:headers="element.options.headers"
:on-exceed="handleExceed"
:file-list="dataModel"
:disabled="element.options.disabled"
:style="{'width': element.options.width}"
>
<div v-if="!preview">
<el-button size="small" type="primary">点击上传</el-button>
</div>
</el-upload>
// js 代码
import COS from 'cos-js-sdk-v5'
import jsCookie from 'js-cookie'
async getSignToken(fileOption) {
let credentials = jsCookie.getJSON('uploadToken')
if (!credentials) {
// GETuploadToken 是后端写的接口,去获取临时身份凭证
const { data } = await GETuploadToken()
// 确保token有效期是一个小时内
var inFifteenMinutes = new Date(new Date().getTime() + 1 * 60 * 59 * 1000)
jsCookie.set('uploadToken', data, { expires: inFifteenMinutes })
credentials = data
}
if (!credentials) {
jsCookie.remove('uploadToken')// 删除userInfo
return this.$message.error('无效上传凭证,请刷新重试')
}
const cos = new COS({
// 这一步是验证临时身份凭证
getAuthorization: async(options, callback) => {
callback({
TmpSecretId: credentials.access_key_id,
TmpSecretKey: credentials.access_key_secret,
SecurityToken: credentials.security_token,
StartTime: ~~(new Date().valueOf() / 1000),
// 建议返回服务器时间作为签名的开始时间,避免用户浏览器本地时间偏差过大导致签名错误
ExpiredTime: credentials.expired_time, // 时间戳,单位秒,如:1580000900
ScopeLimit: true // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用
})
}
})
const url = credentials.upload_dir + '/' + fileOption.file.name
// 验证通过,此处开始上传文件
cos.putObject({
Bucket: credentials.bucket, /* 必须 */
Region: 'ap-shenzhen', /* 存储桶所在地域,需要后端提供 */
Key: url, /* 必须 */
Body: fileOption.file, // 上传文件对象
onProgress: function(progressData) {
this.$message.warning('正在上传,请稍后……')
console.log(progressData, 'progressData')
}
}, (err, data) => {
console.log(err || data)
if (data.statusCode === 200) {
fileOption.url = url
fileOption.status = 'success'
this.handleSuccess(fileOption)
return
}
console.log(`上传失败,原因:${err}`)
this.$message.error(`上传失败,请重试`)
})
},
3.从腾讯云上下载文件
// html
<a href="javascript:void(0)"
:download="link.name"
@click="downloadFile(link)">
{{ link.name }}
</a>
// js
async downloadFile({ url, name, type }) {
this.$message.warning('下载中,请稍后……')
// GETdownloadUrl 是依据后端给的接口写的函数,去获取动态的真正文件地址
const { data: fileUrl } = await GETdownloadUrl({ object_key: url })
if (type.indexOf('image') > -1) {
const image = new Image()
image.src = fileUrl
// 解决跨域 Canvas 污染问题 解决跨域问题-并不好使,需要改对应的请求服务器
image.setAttribute('crossOrigin', 'anonymous')
image.onload = function() {
const canvas = document.createElement('canvas')
canvas.width = image.width
canvas.height = image.height
const context = canvas.getContext('2d')
context.drawImage(image, 0, 0, image.width, image.height)
const url = canvas.toDataURL('image/png')
// 生成一个a元素
const a = document.createElement('a')
// 创建一个单击事件
const event = new MouseEvent('click')
// 将a的download属性设置为我们想要下载的图片名称,若name不存在则使用‘下载图片名称’作为默认名称
a.download = name || '下载图片名称'
// 将生成的URL设置为a.href属性
a.href = url
// 触发a的单击事件
a.dispatchEvent(event)
}
return
}
// 由于跨域,a标签的dowmload失效,需要XMLHttpRequest去解决问题
var x = new XMLHttpRequest()
x.open('GET', fileUrl, true)
x.responseType = 'blob'
x.onload = function(e) {
// 会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。
var url = window.URL.createObjectURL(x.response)
var a = document.createElement('a')
a.href = url
a.download = name
a.click()
}
x.send()
},