1.何时需要从前端直接上传文件到腾讯云cos桶
大多数情况下文件上传是将文件传给后端,后端再处理上传至腾讯云的逻辑。
但也有一些情况,比如上传1000个用户同时上传,上传了1000个文件给服务器,由于上传文件耗时相对较长,就会造成堵塞。这时,就需要从前端直接上传文件到腾讯云的cos桶。这样1000个用户都通过自己的浏览器调用不同的腾讯云上传接口,就可以保证性能啦~
2.具体操作
本方法适用于需要加密程度较高的上传功能————通过前端调用后端接口,获取临时密钥,前台再用临时密钥上传至腾讯云cos桶。如果对加密程度要求不高,可以使用永久密钥.
第一步:安装 SDK
通过 npm 安装环境 SDK: npm 地址。
npm i cos-nodejs-sdk-v5 --save
第二步:新建uploadCos.js。
这里是为了让代码结构规范化,如果追求不高,可以写在页面文件里。
// 腾讯云对象存储
import COS from 'cos-js-sdk-v5'
// getCosSign是向后台请求的接口,传参依照情况而定。一般后台会返回密钥等相关信息
import {getCosSign} from '@kms/api/monthReportManagement/index';
import {Message} from 'element-ui'
var config = {
Bucket: '',
Region: '',
Baseurl: '',
Key:''
};
export default function upload(file, callback) {
// let fileUrl = ''
getCosSign({
fileName: file.name
}).then(response => { // 后台接口返回 密钥相关信息
if (response.success) {
const resData = response.data
const credentials = resData.credentials;
config.Bucket = resData.bucket;
config.Region = resData.region;
config.Baseurl = resData.baseurl;
config.Key = resData.key;
let uploadFileName = Date.parse(new Date())
var cos = new COS({
getAuthorization: function (options, callback) {
callback({
TmpSecretId: credentials.tmpSecretId,
TmpSecretKey: credentials.tmpSecretKey,
XCosSecurityToken: credentials.sessionToken,
StartTime: resData.startTime,
ExpiredTime: resData.expiredTime,
expiration: resData.expiration,
requestId: resData.requestId
})
}
})
cos.putObject({// 此处用了最简单的上传函数,此外,腾讯云还支持分片上传函数等等。
Bucket: config.Bucket, // 存储桶名称
Region: config.Region, // 地区
Key: config.Key, // 图片名称
StorageClass: 'STANDARD',
Body: file, // 上传文件对象
onHashProgress: function (progressData) {
console.log('校验中', JSON.stringify(progressData));
},
onProgress: function (progressData) {
console.log('上传中', JSON.stringify(progressData));
},
},
function (err, data) {// 此处的两个传参是腾讯云返回的,data与上面的data不一样。直接照着写就可以。
// 这里的data如果是个带有Location等的对象,则说明上传成功。
if (err) {
Message({
message: '文件上传失败,请重新上传',
type: 'error',
})
// this.$message.error('文件上传失败,请重新上传')
} else {
let fileUrl = data.Location
callback(fileUrl)
}
}
)}
})
}
第三步:在页面文件里引入upload.js文件,并写入el-upload
简化版el-upload:
.vue文件html部分:
<el-upload
ref="upload"
:action="upload_url"
:before-upload="beforeUpload"
:file-list="fileList"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
</el-upload>
.vue文件js部分
// data:
upload_url: '/api/major/report/upload',
fileList: [],
// methods
beforeUpload(file) {
uploadCos(file,res => {// 有返回值也就是res存在,就代表uploadCos.js文件里的
// --> callback(fileUrl)中的fileUrl存在,也就是说data有值,即上传成功。
if(res){
this.$message.success('上传成功')
}
})
}
完整版el-upload:具体见element-ui的upload组件
.vue文件html部分:
<el-upload
ref="upload"
:action="upload_url"
:before-upload="beforeUpload"
:file-list="fileList"
:auto-upload="false"
:limit="1"
:on-exceed="handleExceed"
:on-change="handleChange"
:on-remove="handleRemove"
>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<el-button
style="margin-left: 10px;"
size="small"
type="primary"
@click="submitUpload(file)"
>提交</el-button>
<div slot="tip" class="el-upload__tip">只能上传pdf/pptx文件,且不超过10M</div>
</el-upload>
.vue文件js部分
import uploadCos from '@kms/api/monthReportManagement/uploadCos'
// data:
upload_url: '/api/major/report/upload',
fileList: [],
fileTypes: '.ppt,.pptx,.pdf',
file: new File([''], '.txt', { type: 'text/plain' }),
// methods:处理上传
submitUpload() {
if (this.file.name === '.txt') {
this.$message({
message: '未发现文件,请重新选择',
type: 'warning',
});
} else {
this.$confirm('请确认是否要上传?', '提示', {
type: 'warning',
}).then(() => {
this.$refs.upload.submit();
});
}
},
// 文件改变更新文件状态
handleChange(file) {
this.file = file;
},
// 处理删除
handleRemove(file, fileList) {
this.file = new File([''], '.txt', { type: 'text/plain' });
},
// 限制上传
handleExceed(files, fileList) {
this.$message.warning(`当前限制选择 1 个文件,本次选择了 ${files.length} 个文件,共选择了 ${files.length + fileList.length} 个文件`);
},
// 上传前校验
beforeUpload(file) {
let _self = this;
var testmsg = file.name.substring(file.name.lastIndexOf('.')).toLowerCase();
if (_self.fileTypes.indexOf(testmsg) < 0) {
_self.$message({
message: testmsg + '类型文件不可上传,请重新选择',
type: 'warning',
});
return false;
}
let fileTypesArr = _self.fileTypes.split(',');
let mpTypes = ['.pdf', '.pptx'];
// 判断文件是否符合要求
if (fileTypesArr.indexOf(testmsg) < 0) {
_self.$message({
message: '上传文件只能是' + _self.fileTypes + '格式!',
type: 'warning',
});
return false;
} else if (mpTypes.indexOf(testmsg) < 0 || file.size / 1024 / 1024 > 10) {
_self.$message({
message: '上传文件过大,大小不可超过10M!',
type: 'warning',
});
return false;
} else if (new Date(this.deadTime + ' 23:59:59') < new Date()) {
this.$message({
type: 'warning',
message: '超过上传时间,禁止上传',
});
return false;
} else {
uploadCos(file,res => {// 有返回值也就是res存在,就代表uploadCos.js文件里的
// --> callback(fileUrl)中的fileUrl存在,也就是说data有值,即上传成功。
if(res){
this.$message.success('上传成功')
}
})
setTimeout(() => {
this.$refs.upload.clearFiles();
}, 1000);
}
},