vant van-uploader 微信内置浏览器 手机拍照 出现刷新或闪退

3 篇文章 0 订阅
3 篇文章 0 订阅

问题原因

根据产品业务,需要在h5页面调用手机的拍照,出现了页面刷新或闪退:

  1. 这是微信内置浏览器内存不足导致的,安卓手机此问题常见,尤其是红米低端机出现概率更高(自己就是用的红米手机);
  2. vant官网在van-uploader组件介绍页面的最下面也说了有这个问题;
  3. 使用input标签,调用拍照也是一样的页面刷新或闪退
  4. 是安卓自身的原因:链接 参考文章.

解决办法(使用van-uploader组件)

  1. van-uploader的标签加capture=“camera”,并限制格式result-type=“file”:
	   <van-uploader
          ref="uploaderRef"
          :before-read="handleBeforeRead"
          result-type="file"
          v-model="fileList"
          capture="camera"
          :afterRead="handleAfterRead"
          max-count="1"
      />
  1. 在handleBeforeRead方法时,对拍照图片进行压缩:
import Compressor from 'compressorjs'
// An highlighted block
return new Promise((resolve, reject) => {
       new Compressor(file, {
         //压缩质量, 0-1
         quality: 0.6,
         //转换的类型,默认为 image/png
         convertTypes: ['image/jpeg'],
         //需要压缩的起始大小,默认5M, 5 * 1000 * 1000
         convertSize: 5000000,
         //压缩成功后处理
         success(result) {
           resolve(result);
         },
         error(err) {
           console.log(err.message);
           proxy.$toast({ type: 'fail', message: err.message })
           reject()
         },
       });
     });
  1. 在handleAfterRead方法时,返回的file是一个对象,并不是后端需要file文件流,需要file.file传给后端,且file.file可能不存在name,需要注意一下。

自己封装的组件

1.组件取名:Vue3Camera.vue (privateUpload是自定义的请求接口,也就是上传图片的接口)


<template>
    <van-uploader
    ref="uploaderRef"
    :before-read="handleBeforeRead"
    v-model="fileList"
    capture="camera"
    result-type="file"
    :afterRead="handleAfterRead"
    max-count="1"
    class="upload-fixed"
    />
</template>
<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
    name: 'Vue3Camera'
})
</script>
<script lang="ts" setup>
import { getCurrentInstance, ref,reactive } from "vue";
import Compressor from "compressorjs";
import { privateUpload } from "@/api/common";
import { v4 as uuidV4 } from 'uuid'
import { Toast, UploaderInstance } from "vant";
const { proxy }: any = getCurrentInstance()
const emits = defineEmits(['uploadSuccess'])
const state = reactive({
    groupId:''
})
const uploaderRef = ref<UploaderInstance>();
let fileList = ref<any[]>([])
const handleBeforeRead:any = (file:any) =>{
    return new Promise((resolve, reject) => {
       new Compressor(file, {
         //压缩质量, 0-1
         quality: 0.6,
         //转换的类型,默认为 image/png
         convertTypes: ['image/jpeg'],
         //需要压缩的起始大小,默认5M, 5 * 1000 * 1000
         convertSize: 5000000,
         //压缩成功后处理
         success(result) {
           resolve(result);
         },
         error(err) {
           console.log(err.message);
           proxy.$toast({ type: 'fail', message: err.message })
           reject()
         },
       });
     });
}

const handleAfterRead = (file:any)=>{
    console.log('file',file)
    if(file.file){
        handleUploadFile(file.file)
    }else{
        proxy.$toast({ type: 'fail', message: '拍照失败' })
    }
}

const handleChooseFile = ()=>{
    uploaderRef.value?.chooseFile();
}

const handleUploadFile = (file: any) => {   
    let fileExtensionArray = file.name.split('.')
    let fileExtension = fileExtensionArray[fileExtensionArray.length - 1]
    let data = ''
    let tempFile = reactive({
        uuid: '',
        name: file.name,
        url: data,
        isImage: true,
        status: 'uploading',
        message: '上传中...',
    })
    state.groupId = uuidV4().replace(/-/g, '')
    fileList.value.push(tempFile)
    let reqData = new FormData()
    reqData.append('files', file)
    reqData.append('groupId', state.groupId)
    privateUpload(reqData)
        .then((res: any) => {
            // proxy.$toast({ type: 'success', message: '操作成功' })
            if (res.code === '0') {
                emits('uploadSuccess', state.groupId)
            } else {
                Toast({ type: 'fail', message: res.message })
            }
        })
        .catch((err) => {
            tempFile.status = 'failed'
            tempFile.message = '上传失败'
        })
}

defineExpose({
    handleChooseFile
})
</script>
<style lang="css" scoped>
.upload-fixed {
    position: absolute;
    right: 100px;
    top: 100px;
    display: none;
}
</style>

2.调用

<Vue3Camera @upload-success="handleUploadSuccess" ref="vue3CameraRef" :key="refreshKey"></Vue3Camera>
const vue3CameraRef = ref<any>()
//调用相机
vue3CameraRef.value.handleChooseFile()

//拍照上传成功
const refreshKey = ref(0)
const handleUploadSuccess = (groupId: any) => {
    refreshKey.value++
    console.log('签到拍照上传成功', groupId)
    //groupId 是上传图片后,后端保存图片的uuid
    //成功之后,你可以调用签到等接口
}

3.虽然这样处理之后,ios与多数安卓没什么问题了,但是红米低端机还是偶尔有问题,如果是在自己的app里使用,建议app提供调用相机的方法来处理。

完结

本人程序员思考很久后,决定离职,目前已经离职,准备换行业折腾了,再见了大家,再见了csdn!!!!!!!!!!

  • 9
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值