vue之vant的h5项目在使用上传图片功能时--ios失败问题

问题描述:

框架相关描述:

vue之vant的h5项目在使用上传图片功能时–ios失败问题;

问题业务场景描述:

  1. 在排查问题时,用ios相机拍照的照片(直接调用ios相机拍的照片)进行上传会显示上传失败,而安卓都不会
  2. 刚开始我以为是图片格式的问题:(看这两种的图片在ios类型是不一样的HEIF和Jpeg,jpeg的格式上传没问题,但是HEIF的上传就会提示上传失败)
    在这里插入图片描述
    在这里插入图片描述

解决方案:

<van-uploader :before-read="beforeRead"
                                      :after-read="afterRead"
                                      :delete="deleteImg" slot="input"
                                      v-model="imageUrls"
                                      :max-count="3"/>
  1. 最终的解决方案是:在afterRead时,将图片进行转流压缩
  2. 实现代码源码:
hanleImage(file) {
                  let self = this;
                  // 看支持不支持FileReader
                  if (!file || !window.FileReader) return;
                  // 创建一个reader
                  let reader = new FileReader();
                  // 将图片2将转成 base64 格式
                  reader.readAsDataURL(file);
                  // 读取成功后的回调
                  reader.onloadend = function () {
                        let result = this.result;
                        let img = new Image();
                        img.src = result;
                        console.log('this.result.lengtht:' + this.result.length);
                        //判断图片是否大于512K,是就直接上传,反之压缩图片   512000
                        if (this.result.length <= 500 * 1024) {
                              console.log('执行此小方案:');
                              self.headerImage = this.result;
                              //进行转流:
                              let file = self.dataURLtoFile();
                              console.log("转流之后的值-file:" + file.name);
                              //处理图片方案:
                              let uploadImgUrlData = upLoaderImg(file);
                              uploadImgUrlData
                                    .then(result => {
                                          self.imageUrlsData.push(result.data);
                                          console.log(result.data);
                                          file.status = 'success';
                                          file.message = '上传成功';
                                    })
                                    .catch(error => {
                                          console.error(error);
                                          file.status = 'failed';
                                          file.message = '上传失败';
                                    });
                        } else {
                              console.log('执行此大方案:');
                              img.onload = function () {
                                    //压缩图片
                                    let data = self.compress(img);
                                    self.headerImage = data;
                                    //进行转流:
                                    let file = self.dataURLtoFile(this.headerImage);
                                    //处理图片方案:
                                    let uploadImgUrlData = upLoaderImg(file);
                                    uploadImgUrlData
                                          .then(result => {
                                                self.imageUrlsData.push(result.data);
                                                console.log(result.data);
                                                file.status = 'success';
                                                file.message = '上传成功';
                                          })
                                          .catch(error => {
                                                console.error(error);
                                                file.status = 'failed';
                                                file.message = '上传失败';
                                          });
                              };
                        }
                  };

            },
            // 压缩图片
            compress(img) {
                  let canvas = document.createElement("canvas");
                  let ctx = canvas.getContext("2d");
                  //瓦片canvas
                  let tCanvas = document.createElement("canvas");
                  let tctx = tCanvas.getContext("2d");
                  // let initSize = img.src.length;
                  let width = img.width;
                  let height = img.height;
                  //如果图片大于四百万像素,计算压缩比并将大小压至400万以下
                  let ratio;
                  if ((ratio = (width * height) / 4000000) > 1) {
                        // console.log("大于400万像素");
                        ratio = Math.sqrt(ratio);
                        width /= ratio;
                        height /= ratio;
                  } else {
                        ratio = 1;
                  }
                  canvas.width = width;
                  canvas.height = height;
                  // 铺底色
                  ctx.fillStyle = "#fff";
                  ctx.fillRect(0, 0, canvas.width, canvas.height);
                  //如果图片像素大于100万则使用瓦片绘制
                  let count;
                  if ((count = (width * height) / 1000000) > 1) {
                        // console.log("超过100W像素");
                        count = ~~(Math.sqrt(count) + 1); //计算要分成多少块瓦片
                        // 计算每块瓦片的宽和高
                        let nw = ~~(width / count);
                        let nh = ~~(height / count);
                        tCanvas.width = nw;
                        tCanvas.height = nh;
                        for (let i = 0; i < count; i++) {
                              for (let j = 0; j < count; j++) {
                                    tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
                                    ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
                              }
                        }
                  } else {
                        ctx.drawImage(img, 0, 0, width, height);
                  }
                  //进行最小压缩
                  let ndata = canvas.toDataURL("image/jpeg", 0.1);
                  tCanvas.width = tCanvas.height = canvas.width = canvas.height = 0;
                  return ndata;
            },
            //将base64转换为文件
            dataURLtoFile() {
                  console.log('执行转流方法');
                  // console.log('执行转流方法' + this.headerImage);
                  var arr = this.headerImage.split(","),
                        bstr = atob(arr[1]),
                        n = bstr.length,
                        u8arr = new Uint8Array(n);
                  while (n--) {
                        u8arr[n] = bstr.charCodeAt(n);
                  }
                  return new File([u8arr], this.files.name, {
                        type: this.files.type
                  });
            },



//上传图片的动作方法我是封装在utils里的
//upLoaderImg.js
import axios from 'axios'		//引入axios
import {Toast} from 'vant'	//引入Toast

async function upLoaderImg(file) {
    try {
        // console.log("上传之前参数:"+file.name)
        let params = new FormData();
        params.append('file', file);
        let config = {
            headers: {
                'Content-Type': 'multipart/form-data'
            }
        };
        const res = await axios.post(process.env.VUE_APP_BASE_URL + '/tool/minioUpload', params, config);
        // console.log("上传之后的结果集:"+res.data.data)
        if (res.data.flag) {
            return res.data;
        } else {
            Toast.fail(res.data && res.data.msg);
            throw new Error(res.data);
        }
    } catch (error) {
        Toast.fail('上传失败');
        throw error;
    }
}

export default upLoaderImg


如有问题欢迎批评改正。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用Vant-UI的van-uploader组件实现头像图片的代码示例: 1. 首先,安装vant-ui和axios: ``` npm install vant axios --save ``` 2. 在Vue项目中引入Vant-UI和axios: ``` import Vue from 'vue'; import Vant from 'vant'; import 'vant/lib/index.css'; import axios from 'axios'; Vue.use(Vant); Vue.prototype.$axios = axios; ``` 3. 在Vue组件中使用van-uploader组件: ``` <template> <van-uploader :disabled="uploadDisable" :before-read="beforeRead" :after-read="afterRead" :preview-options="{closeable: true}" :max-count="1" accept="image/*" :value="avatarUrl" :deletable="deletable" :show-upload="false" > <img v-if="avatarUrl" :src="avatarUrl" class="avatar"/> <div v-else class="avatar-placeholder"></div> </van-uploader> </template> <script> export default { data() { return { avatarUrl: '', // 上成功后图片的地址 deletable: true, // 是否可删除已上图片 uploadDisable: false, // 是否禁用上功能 } }, methods: { beforeRead(file) { // 上前的处理逻辑,如判断图片大小、类型等 // 返回false阻止上,返回true执行上操作 return true; }, afterRead(file) { // 上成功后的处理逻辑 // file对象包含上成功后的图片信息 // file.url即为上成功后的图片地址 this.avatarUrl = file.url; }, }, } </script> <style> .avatar { width: 80px; height: 80px; border-radius: 50%; margin-right: 10px; } .avatar-placeholder { width: 80px; height: 80px; border-radius: 50%; margin-right: 10px; background-color: #f5f5f5; } </style> ``` 以上代码中,van-uploader组件的各个属性含义如下: - :disabled:是否禁用上功能; - :before-read:上前的处理逻辑,返回false阻止上,返回true执行上操作; - :after-read:上成功后的处理逻辑,file对象包含上成功后的图片信息,file.url即为上成功后的图片地址; - :preview-options:图片预览的配置项,如是否可关闭等; - :max-count:上图片数量的最大值; - accept:限制上图片的类型; - :value:上成功后图片的地址; - :deletable:是否可删除已上图片; - :show-upload:是否显示上按钮。 在实现头像上,我们只需将:before-read和:after-read方法中的上逻辑改为上头像即可。同,需要在组件中定义avatarUrl变量,用于保存上成功后的头像地址,并在van-uploader组件中的:value属性和<img>标签中的:src属性中使用该变量,实现上成功后的头像预览效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值