做视频上传的时候有时候需要上传预览图,后端一般可以用FFMPEG来实现,前端也可以直接截图,这个功能不需要后台实现,VUE前端利用canvas画图,然后转换Base64就可以完成。
1.前端代码
<el-form-item label="视频地址" required prop="videoURL">
<el-upload
:action="uploadURL"
:show-file-list="true"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-success="handleUploadvideo"
:headers="headerObj"
name="img"
>
<video
v-if="formData.videoURL"
style="width:300px"
:src="formData.videoURL"
crossOrigin="Anonymous"
controls
/>
<i v-else class="el-icon-plus avatar-uploader-icon" />
</el-upload>
<div class="tips">
只能上传MP4格式文件,文件不能超过50M,您可以拖动视频进度条截取自己需要的截图
</div>
</el-form-item>
<el-form-item label="">
<el-button @click="cutPicture">
截图上传图片封面
</el-button>
<canvas id="myCanvas" style="display: none" />
</el-form-item>
<el-form-item label="图片地址" required prop="imgURL">
<el-upload
:action="uploadURL"
:show-file-list="true"
:on-preview="handlePictureCardPreview"
:on-remove="handleRemove"
:on-success="handleUpload"
:headers="headerObj"
name="img"
>
<el-image
v-if="formData.imgURL"
style="width: 115px; height: 60px"
:src="formData.imgURL"
/>
<i v-else class="el-icon-plus avatar-uploader-icon" />
</el-upload>
<div class="tips">
只能上传jpg/png格式文件,文件不能超过500kb
</div>
</el-form-item>
2.TS脚本
methods: {
// 截取当前帧的图片
cutPicture() {
if (this.formData.videoURL.length === 0) {
this.$message.error('请先上传视频!点击截图后再操作!')
return false
}
var video = document.querySelector('video')
const canvas = document.getElementById('myCanvas') // 获取 canvas 对象
const ctx = canvas.getContext('2d') // 绘制2d
video.crossOrigin = 'anonymous' // 解决跨域问题,也就是提示污染资源无法转换视频
video.currentTime = 2 // 第N帧
video.oncanplay = () => {
canvas.width = video.clientWidth // 获取视频宽度
canvas.height = video.clientHeight // 获取视频高度
// 利用canvas对象方法绘图
ctx.drawImage(video, 0, 0, video.clientWidth, video.clientHeight)
}
// 转换成base64形式
var oGrayImg = canvas.toDataURL('image/jpeg')// 截取后的视频封面
const file = this.getFileByBase64(oGrayImg)
console.log('imgfilename', file)
const formData = new FormData() // 创建一个form类型的数据
formData.append('img', file)
// axios请求,将截图传给后端API
this.loadUploadPhoto(formData).then((res) => {
console.log(res) // 处理成功的函数 相当于success
})
.catch((error) => {
console.log(error) // 错误处理 相当于error
})
},
// base64 转 file----------------------begin
getFileByBase64(data) {
const blobData = this.dataURLtoBlob(data)
return this.blobToFile(blobData)
},
// 1,先将base64转换为blob
dataURLtoBlob(dataurl) {
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 Blob([u8arr], {
type: mime
})
},
// 2,再将blob转换为file
blobToFile(theBlob, fileName) {
theBlob.lastModifiedDate = new Date() // 文件最后的修改日期
theBlob.name = fileName // 文件名
return new File([theBlob], fileName, {
type: theBlob.type,
lastModified: Date.now()
})
},
// base64 转 file--------------------------end
handlePictureCardPreview() {},
handleRemove() {},
handleUpload(data) {
console.log(data)
if (data.code === 200) {
this.$message({
type: 'success',
message: '图片上传成功'
})
console.log('文件上传成功后,图片名=' + data.data.url)
this.formData.imgURL = data.data.url
} else {
this.$message({
type: 'error',
message: '错误:' + data.msg
})
}
},
handleUploadvideo(data) {
if (data.code === 200) {
this.$message({
type: 'success',
message: '视频上传成功'
})
console.log('文件上传成功后,视频名=' + data.data.url)
this.formData.videoURL = data.data.url
console.log(this.formData)
} else {
this.$message({
type: 'error',
message: '错误:' + data.msg
})
}
},
// 封装截图上传
async loadUploadPhoto(file) {
await UploadPhoto(file).then((res) => {
console.log('截图上传', res)
if (res.data.code === 200) {
this.$message({
type: 'success',
message: '添加截图上传成功'
})
console.log('截图文件上传成功后,文件名=' + res.data.data.url)
this.formData.imgURL = res.data.data.url
} else {
this.$message.error('截图上传失败' + res.data.msg)
}
})
},
标签:截图,VUE,const,上传,video,服务器,message,data
From: https://blog.51cto.com/u_52294/8876483