原理:通过调用后台接口获取腾讯云秘钥,然后将秘钥以及文件信息上传到腾讯云,获取文件腾讯云存储信息,最后组件将腾讯云存储信息返回出去,在组件外部调用后台接口将腾讯云信息存到后台。
安装cos-js-sdk-v5依赖
npm i cos-js-sdk-v5 --save
uuid.js文件
在src的utils文件夹中新增uuid.js文件
/* eslint-disable */
export default (len, radix) => {
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
var uuid = [],
i;
radix = radix || chars.length;
if (len) {
// Compact form
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
} else {
// rfc4122, version 4 form
var r;
// rfc4122 requires these characters
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
for (i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
}
return uuid.join('');
}
system.config.js文件
在src的config文件夹中新增system.config.js文件
/**
* 系统配置文件
*/
/* eslint-disable */
// 系统配置 ,在模块中使用方法: this.$CONFIG.xxxx
const config = {
//系统名称
systemTitle:'安全生产标准化管理体系网',
//系统描述
systemDescription:'业界领先的信息聚合平台',
//系统底部 copyright@公司名称
footerComName:'信息科技有限公司',
//腾讯云存储
Bucket: 'test-1256342487',
Region: 'ap-chengdu',
//后台接口地址
serverUrl:'http://123.206.76.136/news/api'
}
export default config
在main.js文件中进行全局属性配置
import config from '@/config/system.config'
// 引入全局自定义配置文件
Vue.CONFIG = Vue.prototype.$CONFIG = config
封装组件
/* eslint-disable space-before-function-paren */
/* eslint-disable space-before-function-paren */
//eslint-disable-next-line vue/valid-template-root
<template>
<div class="clearfix">
<a-upload name="file"
:multiple="true"
:showUploadList="true"
:remove="remove"
:fileList="fileList"
:beforeUpload="beforeUpload"
:customRequest="customRequest"
:accept="accept.join(',')"
class="upload-list-inline"
listType="picture">
<a-button v-if="fileList.length < maxLength">
<a-icon type="upload" />上传
</a-button>
</a-upload>
</div>
</template>
import COS from 'cos-js-sdk-v5'
import { getCredential } from '@/api/upload'
import uuid from '@/utils/uuid'
export default {
name: 'UploadFile',
props: {
/**
* 格式示例:
* [{
uid: '-1',
name: 'xxx.png',
status: 'done',
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
}]
*/
files: {
type: Array,
required: false,
default: () => []
},
maxLength: {
type: Number,
required: false,
default: () => 1000
},
maxSize: {
type: Number,
required: false,
default: () => 102400
},
editable: {
type: Boolean,
required: false,
default: () => true
},
accept: {
type: Array,
required: false,
default: () => []
}
},
data () {
return {
cos: null,
fileList: []
}
},
watch: {
files (list) {
this.fileList = list
}
},
created () {
// 初始化腾讯云上传
this.cos = new COS({
getAuthorization: (options, callback) => {
getCredential().then(data => {
callback({
TmpSecretId: data.tmpSecretId,
TmpSecretKey: data.tmpSecretKey,
XCosSecurityToken: data.sessionToken,
ExpiredTime: data.expiredTime
})
})
}
})
},
methods: {
// 上传之前判断文件大小 即使选择多个文件,beforeUpload也会调用多次
beforeUpload (file) {
// 文件小于100M才能上传
const isSize = Number((file.size / 1024).toFixed(2)) > this.maxSize
if (isSize) {
this.$message.error('请上传文件小于100M')
return false
} else {
return true
}
},
customRequest (info) {
const { file } = info
// debugger
const that = this
const uid = uuid(32)
const extName = that.getExtName(file.name)
// const fileName = `${uid}.${extName}`
const fileName = that.getFileName(file.name) + '' + (new Date()).getTime() + '.' + extName
const size = Number((file.size / 1024).toFixed(2))
const { accept } = that
if (accept.length && !accept.includes(`.${extName}`.toLowerCase())) {
that.$message.error('文件格式错误')
return
}
this.cos.putObject(
{
Bucket: that.$CONFIG.Bucket,
Region: that.$CONFIG.Region,
Key: fileName,
Body: file, // 上传文件对象
onProgress: progressData => {
// that.progress = progressData.percent
}
},
function (err, data) {
if (err) {
that.$notification.error({
message: '文件上传错误',
description: err.Message
})
} else {
const url = `http://${data['Location']}`
that.fileList.push({
uid,
size,
name: file.name,
type: file.type,
status: 'done',
url,
rename: fileName,
extName,
thumbnailUrl: url
})
that.$emit('change', that.fileList)
}
}
)
},
remove (file) {
const that = this
this.fileList = this.fileList.filter(item => item.uid !== file.uid)
that.$emit('change', that.fileList)
},
getExtName (fileName) {
const index = fileName.lastIndexOf('.')
if (index > -1) {
return fileName.substring(index + 1)
} else {
return ''
}
},
getFileName (fileName) {
const index = fileName.lastIndexOf('.')
if (index > -1) {
return fileName.slice(0, index)
} else {
return ''
}
}
}
}
</script>
<style scoped>
/* tile uploaded pictures */
.upload-list-inline >>> .ant-upload-list-item {
float: left;
width: 200px;
margin-right: 8px;
}
.upload-list-inline >>> .ant-upload-animate-enter {
animation-name: uploadAnimateInlineIn;
}
.upload-list-inline >>> .ant-upload-animate-leave {
animation-name: uploadAnimateInlineOut;
}
</style>
使用
<upload-file
:accept="['.doc','.docx','.ppt','.pptx','.pdf','.pdfx','.xls','.xlsx']"
:files="fileList"
@change="uploadFile"></upload-file>
// 上传附件返回数据
uploadFile(files){
console.log("uploadFile",files)
this.articleAttachmentList = files.map(item=>({
attachmentExtensionName:item.extName,//文件扩展名
attachmentLogicalFilename:item.name,//文件显示名
attachmentPhysicalFilename:item.rename,//文件存储名
attachmentSize:item.size,//文件大小
attachmentUrl:item.url,//文件路径
}))
},
// 获取数据给组件显示
this.fileList = articleAttachmentList.map((item,index)=>({
uid:index,
name: item.attachmentLogicalFilename,
status:"done",
url: item.attachmentUrl,
reName: item.attachmentPhysicalFilename,
extName: item.attachmentExtensionName,
size:0,
thumbnailUrl:""
}))