上传视频预览 Vue 完整代码(获取视频的第一帧)
最编程
2024-03-08 14:08:49
...
<template>
<div>
<el-upload
ref="upload"
:limit="uploadLimit"
list-type="picture-card"
:accept="uploadAccept"
:before-upload="beforeUpload"
:headers="headers"
:on-preview="handlePreview"
:on-success="handleSuccess"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:action="action"
:file-list="fileList"
>
<i slot="default" class="el-icon-plus" />
</el-upload>
<!-- 预览部分 -->
<el-dialog :visible.sync="dialogImage">
<img width="400px" :src="dialogUrl" alt="">
</el-dialog>
<el-dialog :visible.sync="dialogVideo">
<video width="600px" :src="dialogUrl" controls />
</el-dialog>
<div v-if="videoList[0]" style="position:absolute; right: 999999px">
<canvas id="mycanvas" />
<video id="upvideo" :src="videoList[0].url" style="width:320px;height:200px;" controls="controls" />
</div>
</div>
</template>
<script>
export default {
data() {
return {
uploadLimit: 1,
imgType: 1, // 1图片 2视频
worksUpdateType: 3 // 1图片 2视频 3均可
}
},
computed: {
uploadAccept() {
let text = '.png, .jpg, .mp4'
switch (this.worksUpdateType) {
case 1:
text = '.png, .jpg'
break
case 2:
text = '.mp4'
break
case 3:
text = '.png, .jpg, .mp4'
break
}
return text
}
},
methods: {
// 上传文件大小、格式限制
beforeUpload(file) {
if (file.type !== 'video/mp4') {
this.uploadLimit = 20
this.imgType = 1
} else {
const isHaveImg = this.fileList.some(item => item.suffix === 'jpg' || item.suffix === 'png')
if (isHaveImg && (this.videoSrc !== '' || this.imgType === 1)) {
this.handleExceed()
return false
}
this.uploadLimit = 1
this.imgType = 2
}
const testmsg = file.name.substring(file.name.lastIndexOf('.') + 1)
const extension = testmsg === 'mp4'
const isJPG = file.type === 'image/jpg' || file.type === 'image/jpeg' || file.type === 'image/png'
const isLt5M = file.size / 1024 / 1024 < 5
const isLt2M = file.size / 1024 / 1024 < 100
if (isJPG) {
if (!isLt5M) {
this.$message.error('上传图片大小不能超过 5MB!')
}
} else if (extension) {
if (!isLt2M) {
this.$message.error('上传视频大小不能超过 100MB!')
}
}
const n = this.worksUpdateType
if (n === 1 && !isJPG) {
this.$message.error('上传图片只能是 JPG、PNG格式!')
return isJPG && isLt5M
} else if (n === 2 && !extension) {
this.$message.error('上传视频只能是 MP4格式!')
return extension && isLt2M
} else if (n === 3 && !isJPG && !extension) {
this.$message.error('上传文件只能是 JPG、PNG、MP4格式!')
return (isJPG && isLt5M) || (extension && isLt2M)
}
},
// 上传成功图片/视频区分处理(如果为视频截取第一帧)
handleSuccess(res, file, fileList) {
let newFile = null
if (res.success) {
newFile = res.data.mapList[0]
if (newFile.suffix === 'mp4') {
this.fileList = []
this.fileList.push(newFile)
this.videoList = [newFile]
this.videoSrc = newFile.url
// 需要DOM更新后操作,否则会报错
this.$nextTick(() => {
this.findvideocover(newFile.url)
})
} else {
this.fileList.push(newFile)
this.form.imgPath = newFile.url
}
}
},
// 截取视频第一帧作为播放前默认图片
async findvideocover(url, file) {
const video = document.querySelector('#upvideo') // 获取视频对象
video.src = url // url地址 url跟 视频流是一样的
var canvas = document.getElementById('mycanvas') // 获取 canvas 对象
const ctx = canvas.getContext('2d') // 绘制2d
video.crossOrigin = 'anonymous' // 解决跨域问题,也就是提示污染资源无法转换视频
video.currentTime = 1 // 第一帧
video.oncanplay = () => {
canvas.width = video.clientWidth // 获取视频宽度
canvas.height = video.clientHeight // 获取视频高度
// 利用canvas对象方法绘图
ctx.drawImage(video, 0, 0, video.clientWidth, video.clientHeight)
// 转换成base64形式
this.imgsrc = canvas.toDataURL('image/png') // 截取后的视频封面
// 将base64转化成图片上传获取地址url
const res = this.dataURLtoFileFun(this.imgsrc, 'file.jpg')
this.getVideoImgUrl(res)
}
},
dataURLtoFileFun(dataurl, filename) {
// 将base64转换为文件,dataurl为base64字符串,filename为文件名(必须带后缀名,如.jpg,.png)
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, { type: mime })
},
// 将截取到第一帧的图片上传拿到url地址
async getVideoImgUrl(res) {
const formData = new FormData()
formData.append('file', res)
formData.append('size', 100)
formData.append('unit', 'M')
const { data } = await worksList.uploadFile(formData)
this.fileList.push(data.mapList[0])
this.form.imgPath = data.mapList[0].url
},
handleRemove(file, fileList) {
if (file.suffix === 'mp4') {
this.uploadLimit = 20
this.imgType = 1
}
if (file.status === 'success') this.fileList = fileList
this.dialogUrl = null
},
handlePreview(file) {
if (this.videoSrc !== '') {
this.dialogVideo = true
this.dialogUrl = this.videoSrc
} else {
this.dialogUrl = file.url
this.dialogImage = true
}
},
}
}
</script>