解决H5调用安卓相机实现拍照并上传
解决H5调用安卓相机实现拍照并上传最近在开发中遇到一个问题,要在APP内嵌的H5页面中实现拍照录像并上传到后端服务器.刚开始我直接想到:<input type="file" accept="image/*" capture="camera">由于项目用vant UI,于是用了Uploader文件上传组件,大家可自行查看实现方法:https://youzan.github.io/vant
最近在开发中遇到一个问题,要在APP内嵌的H5页面中实现拍照录像并上传到后端服务器。
刚开始我直接想到:
<input type="file" accept="image/*" capture="camera">
由于项目用vant UI,于是用了Uploader文件上传组件,大家可自行查看实现方法:https://youzan.github.io/vant/#/zh-CN/uploader。这种方法在浏览器上使用没有毛病,可是嵌入APP后却出现只能打开相册不能打开相机的问题,加上产品经理想拍照后还可以对照片进行编辑,这是H5直接调用相机所不具备的。于是与原生APP开发的同事沟通后,决定采用调用安卓相机的方案。
首先在页面上写一个按钮,
<van-button icon="photograph" type="primary" @click="appPhotograph" native-type="button" />
点击按钮去调用安卓的方法,实现打开摄像头:
methods: {
appPhotograph() {
window.Android.takePicture() // 安卓提供的打开摄像头方法,此方法要安卓开发提供
},
}
这个时候实现了打开摄像头并拍照,对图片进行编辑等功能,下一步就是要解决H5这边如何进行图片上传。
我们知道通过input type=file 实现的拍照我们是可以拿到文件流的,然后再把这个文件流传给后端,就实现了文件上传,所以接着我们就要拿到安卓那边的文件流。于是安卓那边又提供了一个返回文件的方法: takePictureCallBack(),直接上代码吧:
takePictureCallBack(content, name, path, size) { // 获取base64图片,安卓开发提供
let src = `data:image/jpeg;base64,${content}` // 由于content内容没有data:image/jpeg;base64,所以拼接上,如果你的已经有了就无需拼接
let file = this.base64toFile(src)
let fileData = new FormData()
fileData.append('file', file)
fileData.append('tenantId', 'prosCenter') // 上传文件附带的参数,请根据你的业务需求而定,若无请忽略
upLoadFileApi(fileData).then(res => { // 调用文件上传接口,请自行封装
// 这里放上传成功的业务处理
Notify({ type: 'success', message: '上传成功' });
let fileObj = res.datas
this.forms.attachmentsList.push(fileObj) // 将上传后的文件显示在页面上,请根据你的业务需求而定,this.forms.attachmentsList数组请自行定义
}).catch(error => {
Notify({ type: 'warning', message: '上传失败' });
})
},
base64toFile (dataurl, filename = 'file') { // 将base64格式转为file文件流
let arr = dataurl.split(',')
let mime = arr[0].match(/:(.*?);/)[1]
let suffix = mime.split('/')[1]
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
},
解释一下以上代码,由于安卓开发同事那边说无法直接将文件通过file格式传过来,于是通过base64格式传,所以我们拿到的base64格式还要转成file格式,才能上传到服务器上。
这里有一点要注意,这种没有通过类似点击这样的动作调用的方法,我们要把它挂载在window下面,否则会无法调用:
mounted() {
window.takePictureCallBack = this.takePictureCallBack;
}
磕磕碰碰了许久,终于实现了产品想要的功能,在此分享给遇到同样问题的前端开发工程狮们。
更多推荐
所有评论(0)