van-uploader拍照上传多个文件报错ERR_UPLOAD_FILE_CHANGED问题

移动端使用van-uploader连续上传两个图片,ajax接口也会出现报错ERR_UPLOAD_FILE_CHANGED,这个地方还真要用到上一篇提供的方案,先把图片转成base64字符串,上传前再转成File对象。

1.问题描述

同上一篇el-upload拍照上传多个文件报错 ERR_UPLOAD_FILE_CHANGED问题,移动端使用van-uploader选择多个文件一起上传也遇到这个问题,报错也一样:ERR_UPLOAD_FILE_CHANGED

2.问题分析

这里的问题是浏览器兼容性问题,我用红米手机自带浏览器连续拍多张图片,一起上传没有这个问题,Android套壳之后就不行,估计Android套壳使用的浏览器和红米浏览器的内核不一样,前者不支持这个特性,参考下面参考链接。

3.解决方案

拍照选择文件的时候把文件转成base64字符串同时清除input框内容,点确定的时候把base字符串还原成文件,然后传给外面组件,这里是用store保存并传数据的。

van-uploader和el-upload有点区别,前者只有after-read,befor-read事件,没有fiechange事件,这里使用原生的input标签来实现这个功能。

javascript关键代码:

//图片转base64
const fileToBase64 = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsDataURL(file)
    reader.onload = () => resolve(reader.result)
    reader.onerror = (error) => reject(error)
  })
}

// base64转图片
const base64ToFile = (base64: any, fileName: any) => {
  const arr = base64.split(',')
  const mime = arr[0].match(/:(.*?);/)[1]
  const bstr = atob(arr[1])
  let n = bstr.length 
  const u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], fileName, { type: mime })
}

html关键代码:

  <div class="full-screen list-container">
    <div class="content-wrapper photo-wrapper" :style="{marginTop: contentTop + 'px'}">
      <!-- <van-uploaderer v-model="photoStore.photoList" multiple/> -->
      <div class="container" @click="onClickPicture">
        <img class="image_picture" :src="getAssetURL('icon_picture.png')"/>
        <div class="text">上传</div>
      </div>
      <input type="file" ref="refInput" accept="image/*" @change="onFileChange" class="file-packer" id="uploadFile" hidden>
    </div>
    <div class="image-wrapper">
      <div v-for="(item, index) in obj.fileList" :key="index" class="image-item">
        <img :src="item.img" alt="" class="item"/>
        <img :src="getAssetURL('icon_delete_photo.png')" alt="" class="delete" @click="onDelClick(index)"/>
      </div>
    </div>
    <div class="footer-wrapper">
      <div class="btn-box">
        <van-button type="primary" @click="onOk">确定</van-button>
      </div>
    </div>
  </div>
const onFileChange = e => {
  fileToBase64(e.target.files[0]).then(res => {
    obj.fileList.push({img: res, name: e.target.files[0].name})
    refInput.value.value = ''
  })
}

const onOk = () => {
  const files = obj.fileList.map((item, i) => {
    return {file: base64ToFile(item.img, `_${i + 1}_${item.name}`),img: item.img} 
  })
  photoStore.setPhotoList(files)
  refInput.value.value = ''
  router.back()
}

最后结果:
image

4.总结

文件上传虽然可以使用html+javascript来实现,但是由于浏览器差异还是有很多的差异和兼容性问题。

参考:
1.https://stackoverflow.com/questions/57516930/prevent-html-file-input-from-selecting-files-in-google-drive-while-using-android

posted @ 2024-06-26 11:04  nd  阅读(140)  评论(0编辑  收藏  举报