需求
移动端需要显示上传的视频,视频第一帧作为封面图,ios端支持且兼容性好,安卓端显示延迟2s左右,优化体验,上传时需要生成封面图。
上代码
export function getVideoBase64 (url: string) {
url = handleFilePath(url)// 通过代理方式,支持跨域
return new Promise(function (resolve, reject) {
let dataURL = ''
let video = document.createElement('video')
video.setAttribute('crossOrigin', 'anonymous')// 处理跨域,需要服务器支持跨域
video.setAttribute('src', url)
video.setAttribute('preload', 'auto')
video.setAttribute('width', '688px')
video.setAttribute('height', '400px')
video.setAttribute('style', 'object-fit:scale-down')
video.addEventListener('loadeddata', async function () {
let canvas:any = document.createElement('canvas')
let width = video.width // canvas的尺寸和图片一样
let height = video.height
canvas.width = width
canvas.height = height
canvas.getContext('2d').drawImage(video, 0, 0, width, height) // 绘制canvas
dataURL = canvas.toDataURL('image/jpeg') // 转换为base64
let file = dataURLtoFile(dataURL, '封面图.jpg') // 转成file
let { data } = await uploadFile({ file: file, type: 'jokefooww' })// 上传视频
resolve(data.url)
})
})
}
// 对附件链接进行处理,使之同源,支持设置 download
export function handleFilePath (path:string) {
let res = /^https?://[a-zA-Z-]+.XXXX.com/(.+)$/.exec(path)
let url = res ? res[1] : path
return `/fileapi/${url}`
}
// 将base64转换为blob,直接转file浏览器兼容问题
export function dataURItoBlob (base64Data:any) {
let byteString
if (base64Data.split(',')[0].indexOf('base64') >= 0) { byteString = atob(base64Data.split(',')[1]) } else { byteString = unescape(base64Data.split(',')[1]) }
let mimeString = base64Data.split(',')[0].split(':')[1].split(';')[0]
let ia = new Uint8Array(byteString.length)
for (let i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i)
}
return new Blob([ia], { type: mimeString })
};
// 将blob转换为file
function dataURLtoFile (dataurl: string, filename: string) {
// 获取到base64编码
const arr = dataurl.split(',')
// 将base64编码转为字符串
const bstr = window.atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n) // 创建初始化为0的,包含length个元素的无符号整型数组
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], filename, {
type: 'image/jpeg'
})
}