产品提了这样一个需求:
移动端拍照上传后图片不保存在用户设备上,试了好几种方法,uni-file-picker、uni.chooseImage、input type=‘file’,安卓手机都会默认把图片保存在手机,于是各种查资料,找到了以下方法,已验证可行。
1、获取摄像头权限并显示视频流:
使用navigator.mediaDevices.getUserMedia()获取摄像头权限,并将视频流显示在video标签中。
2、拍照:
使用HTML的canvas标签来截取当前摄像头的画面,并将其转换为图片格式。
3、上传图片:
使用uniapp的uni.uploadFile()方法将图片上传到服务器。
<view class="container">
<button @click="initCamera">打开摄像头</button>
<button @click="takePhoto">拍照</button>
</view>
data() {
return {
stream: null,
videoElement: null
}
}
mounted() {
this.createVideoElement()
},
methods: {
createVideoElement() {
// 一定要用createElement创建 video和canvas 元素,否则用不了其中的方法
this.videoElement = document.createElement('video')
this.videoElement.setAttribute('autoplay', '')
this.videoElement.setAttribute('muted', '')
this.videoElement.setAttribute('playsinline', '')
// 添加到 DOM 中
const container = document.querySelector('.container')
container.appendChild(this.videoElement)
},
async initCamera() {
if (this.stream) {
this.stopCamera()
}
try {
const constraints = { video: { facingMode: 'environment' }}
const stream = await navigator.mediaDevices.getUserMedia(constraints)
this.stream = stream
this.videoElement.srcObject = stream
} catch (error) {
console.error('Error accessing camera:', error)
}
},
// 关闭摄像头
stopCamera() {
if (this.stream) {
this.stream.getTracks().forEach(track => track.stop())
this.stream = null
this.videoElement.srcObject = null
}
},
takePhoto() {
this.captureImage()
this.stopCamera()
},
async captureImage() {
const canvas = document.createElement('canvas')
canvas.width = this.videoElement.clientWidth
canvas.height = this.videoElement.clientHeight
const ctx = canvas.getContext('2d')
ctx.drawImage(this.videoElement, 0, 0, canvas.width, canvas.height)
// 转化成base64的编码格式
const dataUrl = canvas.toDataURL('image/jpeg')
this._uploadFileBase64(dataUrl)
},
// 上传到远程地址
_uploadFileBase64(imgUrl) {
uploadFileBase64(imgUrl).then(response => {
if (response && response.SavePath) {
console.log(response.SavePath)
this.$uniToast('上传成功')
} else {
this.$uniToast('上传失败')
}
})
}
}