vue 调取摄像头录制视频并上传到后端(部分浏览器兼容)
项目场景:使用input调取手机摄像头,录制视频并上传到客户端问题描述:在input发生change事件时,使用e.target.files获取文件,部分浏览器无法获取到文件。@Overridepublic void run() {bytes = mmInStream.read(buffer);mHandler.obtainMessage(READ_DATA, bytes, -1, buffer)
项目场景:
使用input调取手机摄像头,录制视频并上传到客户端
问题描述:
<template>
<div>
<button>点击上传</button>
<input type="file" @change="openCamera($event)" accept="video/*" capture="user" />
<!-- accept="video/*" :accept 属性只能与 <input type="file"> 配合使用。-->
<!-- 它规定能够通过文件上传进行提交的文件类型。 -->
<!-- 指定capture属性调用默认相机,摄像,录音功能 -->
</div>
</template>
在input发生change事件时,在测试的时候发现ios的微信内置浏览器无法触发FileReader 的onload事件,以及URL.createObjectURL()。
解决方案:
方法解读:
FileReader.onload:读取成功完成时触发。也可通过onload属性获得。
FileReader.loadend :读取成功或失败时触发。也可通过onloadend属性获得。
FileReader.result :只读 文件的内容。此属性仅在读取操作完成后才有效,并且数据的格式取决于用于启动读取操作的方法。
URL.createObjectURL和FileReader.readAsDataURL:
URL.createObjectURL:静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。
这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象,直接绑定给src即可。
FileReader.readAsDataURL :方法用于读取指定Blob或的内容File。读取操作完成后,readyState变成DONE,并loadend触发。那时,该result属性包含数据作为数据:URL表示文件数据为base64编码的字符串。
主要区别:
通过FileReader.readAsDataURL(file)可以获取一段data:base64的字符串
通过URL.createObjectURL(blob)可以获取当前文件的一个内存URL
错误代码:
经测试,代码安卓的自带浏览器,安卓的微信,均可上传成功,uc浏览器,ios 的微信内置浏览器无法上传,ios Safari可以成功上传。(测试不全)
methods: {
// 调用摄像头 上传视频
openCamera(e) {
let that = this;
let duration;
let selectedFile = e.target.files[0];
let reader = new FileReader(); //这是核心,读取操作就是由它完成.
reader.onload = function(e) {
let strContent = this.result;
//获取视频或者音频时长
let fileurl = URL.createObjectURL(selectedFile);
let audioElement = new Audio(fileurl);
//经测试,发现audio也可获取视频的时长
audioElement.addEventListener("loadedmetadata", function(_event) {
duration = audioElement.duration;
if (duration > 8) {
that.$message.error("视频时间过长,请重新录制");
} else {
that.base64ToFile(strContent);
}
});
};
reader.readAsDataURL(selectedFile); //读取文件的内容,也可以读取文件的URL
},
// 将bes64转成文件
base64ToFile(base64Data) {
// base64转blob
let arr = base64Data.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
let blob = new Blob([u8arr], {
type: mime
});
// 将blob转为文件
blob.lastModifiedDate = new Date();
blob.name = "file";
let config = {
//其他配置
}
this.Request(blob, config); //发起请求
},
Request(data, config) {
axios.post('/url', data, config).then(res => {
console.log("成功")
}).catch(err => {
console.log("失败")
})
}
},
正确代码
仅是openCamera方法不同。测试发现ios 微信内置浏览器无法通过Audio或者Video获取视频时长,由于ios对视频压缩较好,9秒的视频大概1兆,所以只单独对ios的微信通过限制视频大小来限制时长。
openCamera(t) {
// 判断浏览器
let userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
let MicroMessenger = userAgent.indexOf("MicroMessenger") > -1; //判断是否微信内置浏览器
let isIPhone = userAgent.indexOf("iPhone") > -1; //判断是否是iPhone
let i = t.target.files[0];
let fileurl = URL.createObjectURL(i);
let duration;//视频时长
let that = this;
let n = new FileReader();
let fileSize = i.size / 1024 / 1024; //获取文件大小
n.readAsDataURL(i);
n.addEventListener("loadend", function() {
let strContent = n.result;
if (MicroMessenger && fileSize) {
if (fileSize > 1) {
console.log("文件大小" + fileSize);
that.$message.error("视频时间过长,请重新录制");
} else {
that.base64ToFile(strContent);
}
} else {
let audioElement = new Audio(fileurl);
//经测试,发现audio也可获取视频的时长
audioElement.addEventListener("loadedmetadata", function(_event) {
duration = audioElement.duration;
console.log("视频时长:" + duration);
if (duration > 8) {
that.$message.error("视频时间过长,请重新录制");
} else {
that.base64ToFile(strContent);
}
});
}
});
},
以上为个人经验,如有错误请指出。
更多推荐
所有评论(0)