|
|
<template> <div class="components_upload"> <!-- <div v-if="isTheme"> <el-button class="cont_upload_btn" round type="primary">选择文件</el-button> <input id="upFile" ref="inputfile" type="file" name="upFile" @change="changeFile($event)" /> </div> --> <el-button class="cont_upload_btn" round type="primary">{{ isTheme ? '选择文件' : '上传' }}</el-button> <input id="upFile" type="file" name="upFile" @change="changeFile($event)" /> <input v-if="isTheme" type="button" name="开始上传" value="开始上传" class="start_upload" @click="uploadFile()" />
<!-- 上传列表layer --> <div v-if="!isTheme" class="upload_layer"> <el-dialog title="上传列表" :close-on-click-modal="false" :show-close="false" :visible.sync="uploadListVisible" height="384px" > <el-table :data="fileData" :header-cell-style="{ color: '#333' }"> <el-table-column align="center" prop="fileNames" label="文件名" /> <el-table-column align="center" prop="formatType" label="类型" /> <el-table-column align="center" prop="fileSize" label="大小" /> <el-table-column align="center" prop="filePercentTxt" label="状态"> <template slot-scope="scope"> <div class="loadingModal" :style="{ 'height': '100%' }"> <el-progress v-if="scope.row.filePercent != 0 && scope.row.filePercent != 100" :stroke-width="6" :percentage="scope.row.filePercent" /> <span v-else>{{ scope.row.filePercentTxt }}</span> </div> </template> </el-table-column> <el-table-column align="center" prop="handle" label="操作"> <template slot-scope="scope"> <!-- <el-button type="primary" round class="on_off_btn" style="width: 50px; display: inline-block;" @click="controlUpload(scope.$index)" >{{ uploadStatus ?'暂停':'继续' }}</el-button> --> <el-button type="info" round style="width: 50px; display: inline-block;" class="upload_delt" @click="deltUpload(scope.$index)" >删除</el-button> </template> </el-table-column> </el-table> <div class="upload_list_right"> <div class="upload_list_btn"> <el-button>点击上传</el-button> <input id="upLoadFile" ref="inputfile" type="file" name="upFile" @change="changeFile($event)" /> </div> <div class="upload_return" @click="uploadListVisible=false">返回</div> </div> </el-dialog> </div> </div> </template> <script> import * as qiniu from 'qiniu-js' import { getQiniuToken, FectchUploadTokenAndOps } from '@/api/upload/upload' let observable export default { name: 'Qiniu', props: { isTheme: { type: Boolean, required: true } }, data() { return { file: null, token: '', baseurl: 'qiniu.aiyxlib.com', fileData: [], fileNames: '', formatType: '', postfix: '', fileSize: '', duration: 0, uploadListVisible: false, subscription: '', uploadFileUrl: null, filePercent: 0, uploadStatus: false, isActiveType: null } }, mounted() { this.getQiniuToken() localStorage.removeItem('compareName') }, methods: { changeFile(e) { // 获取文件
this.file = e.target.files[0] this.$emit('getName', this.file.name) this.formatType = this.file.type.substring(0, this.file.type.indexOf('/')) if (this.isActiveType == 0) { if (this.formatType != 'image') { this.$message.error('请上传图片文件!') return } } else if (this.isActiveType == 1) { if (this.formatType != 'video') { this.$message.error('请上传视频文件!') return } } else if (this.isActiveType == 2) { if (this.formatType != 'audio') { this.$message.error('请上传音频文件!') return } } this.fileNames = this.file.name this.postfix = this.fileNames.substring( this.fileNames.lastIndexOf('.') + 1, this.fileNames.length ) this.fileSize = this.file.size if (this.formatType === 'image') { const isJPG = this.file.type === 'image/jpeg' || this.file.type === 'image/png' || this.file.type === 'image/bmp' || this.file.type === 'image/gif' const isLt2M = this.file.size / 1024 / 1024 < 4 if (!isJPG) { this.$message.error('图片只支持bmp、jpg、png、gif格式的文件') } if (!isLt2M) { this.$message.error('图片大小不能超过 4MB !') } } const isRepeat = this.fileData.map(item => item.key).indexOf(this.fileNames) if (isRepeat == -1) { this.fileData.push({ fileNames: this.fileNames, formatType: this.formatType, fileSize: this.fileSize, filePercent: 0, filePercentTxt: '上传中', key: this.fileNames, uploadStatus: false }) if (!this.isTheme) { setTimeout(() => { this.uploadFile() }, 1000) } } else { if (!this.isTheme) { this.$message({ message: '该素材上传列表内已存在~', type: 'info' }) } } // this.getOpsToken()
this.uploadListVisible = true }, getQiniuToken() { getQiniuToken().then(res => { this.token = res.data }) }, getOpsToken() { const name = Date.parse(new Date()) + '.mp4' const name1 = Date.parse(new Date()) const param = { tFileName: name1, tExtName: this.postfix } FectchUploadTokenAndOps(param).then(res => { this.token = res.data const _this = this const putExtra = { fname: name1, params: {}, mimeType: null } const config = { useCdnDomain: true, region: qiniu.region.z0, concurrentRequestLimit: 3, checkByMD5: true, retryCount: 3 } const token = this.token observable = qiniu.upload( this.file, name, token, putExtra, config ) _this.percentage = 10 }) }, getVideoDuration(fileUrl) { const _this = this const audioElement = new Audio(fileUrl) audioElement.addEventListener('loadedmetadata', function() { _this.duration = parseInt(audioElement.duration) // 得到时长为秒,小数,182.36
// self.ruleForm.videoDuration = parseInt(result) // 转为int值
}) }, uploadFile() { // 当前VUE中的this 是指向实例,相当于父级,指向指不到子级中。所需需要一个变量 _this 存储this得指向。
const _this = this _this.filePercent = 0 _this.uploadStatus = false let compareChunks = [] var finishedAttr = [] // 获取身份的token
const token = _this.token // 上传时的配置
var config = { useCdnDomain: true } // 设置文件的配置
var putExtra = { fname: '', params: {}, mimeType: null } // 实例化七牛云的上传实例
observable = qiniu.upload(_this.file, _this.file.name, token, putExtra, { resumingByFileSize: 4 * 1024 * 1024 }, config) // 设置实例的监听对象
localStorage.setItem('currentFile', _this.file.name) // 接收上传进度信息
var next = function(res) { const currentFile = localStorage.getItem('currentFile') const index = _this.fileData.map((item) => item.key).indexOf(currentFile) var chunks = res.chunks || [] var total = res.total // 这里对每个chunk更新进度,并记录已经更新好的避免重复更新,同时对未开始更新的跳过
for (var i = 0; i < chunks.length; i++) { if (chunks[i].percent === 0 || finishedAttr[i]) { continue } if (compareChunks[i].percent === chunks[i].percent) { continue } if (chunks[i].percent === 100) { finishedAttr[i] = true } } compareChunks = chunks _this.filePercent = parseInt(total.percent) _this.$nextTick(function() { _this.fileData[index].filePercent = _this.filePercent }) } // 接收上传错误信息
var error = function(err) { console.log(err) } // 接收上传完成后的信息
var complete = function(res) { const index = _this.fileData.map((item) => item.key).indexOf(res.key) _this.uploadFileUrl = 'http://' + _this.baseurl + '/' + res.key // 上传完成后调用保存素材方法
_this.getVideoDuration(_this.uploadFileUrl) _this.$nextTick(function() { _this.fileData[index].filePercentTxt = '上传成功' _this.fileData[index].filePercent = 100 }) setTimeout(() => { _this.$emit('saveMaterial') }, 200) document.getElementById('upFile').value = '' document.getElementById('upLoadFile').value = '' localStorage.removeItem('currentFile') // localStorage.removeItem('currentCompareName')
} var subObject = { next: next, error: error, complete: complete } _this.controlUpload = function() { _this.uploadStatus = !_this.uploadStatus if (_this.uploadStatus) { _this.subscription = observable.subscribe(subObject) // 调用sdk上传接口获得相应的observable,控制上传和暂停
} else { _this.subscription.unsubscribe() } } _this.controlUpload() // 上传开始
// subscription = observable.subscribe(observer)
}, deltUpload(index) { this.subscription.unsubscribe() this.fileData.splice(index, 1) } } } </script>
<style lang="scss" scoped> .components_upload{ position: relative; } #upFile, #upLoadFile{ display: block; width: 114px; height: 34px; padding: 0; font-size: 14px; border: none; opacity: 0; } .cont_upload_btn{ position: absolute; left: 0; top: 0; }
.upload_list_btn{ position: relative; ::v-deep .el-button { position: absolute; left: 0; top: 0; width: auto; height: auto; margin: 0; padding: 0; font-size: 14px; font-weight: bold; color: #3a8aeb; } #upLoadFile{ width: 60px; } } ::v-deep .el-progress-bar__outer{ background-color: transparent; } ::v-deep .el-progress-bar__inner { background-image: linear-gradient(to right, #40cbfe, #3a8aeb) }
</style>
|