移动端H5实现图片上传

本文介绍了如何使用H5原生API实现移动端图片上传,包括FormData、base64、Blob对象和FileReader对象的基础知识,以及应对手机兼容性问题的解决方案。文中详细阐述了图片上传的思路,从监听input事件获取文件,到图片压缩、转换为base64,再到使用FormData上传,并探讨了多图并发上传的实现策略。
摘要由CSDN通过智能技术生成

需求

公司现在在移动端使用webuploader实现图片上传,但最近需求太奇葩了,插件无法满足我们的PM
经过商讨决定下掉这个插件,使用H5原生的API实现图片上传。

7.3日发布:单张图片上传

9.29日更新:多张图片并发上传

11.06日更新:常见问题

效果图:
uploader

基础知识

上传图片这块有几个知识点要先了解的。首先是有几种常见的移动端图片上传方式:

FormData

通过FormData对象可以组装一组用 XMLHttpRequest发送请求的键/值对。它可以更灵活方便的发送表单数据,因为可以独立于表单使用。如果你把表单的编码类型设置为multipart/form-data ,则通过FormData传输的数据格式和表单通过submit() 方法传输的数据格式相同。

这是一种常见的移动端上传方式,FormData也是H5新增的 兼容性如下:
clipboard.png

base64

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。 由于2的6次方等于64,所以每6个位元为一个单元,对应某个可打印字符。 三个字节有24个位元,对应于4个Base64单元,即3个字节可表示4个可打印字符。

base64可以说是很出名了,就是用一段字符串来描述一个二进制数据,所以很多时候也可以使用base64方式上传。兼容性如下:

clipboard.png

还有一些对象需要了解:

Blob对象

一个 Blob对象表示一个不可变的, 原始数据的类似文件对象。Blob表示的数据不一定是一个JavaScript原生格式。 File 接口基于Blob,继承 blob功能并将其扩展为支持用户系统上的文件。

简单说Blob就是一个二进制对象,是原生支持的,兼容性如下:

clipboard.png

FileReader对象

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

FileReader也就是将本地文件转换成base64格式的dataUrl。

clipboard.png

图片上传思路

准备工作都做完了,那怎样用这些材料完成一件事情呢。
这里要强调的是,考虑到移动端流量很贵,所以有必要对大图片进行下压缩再上传。
图片压缩很简单,将图片用canvas画出来,再使用canvas.toDataUrl方法将图片转成base64格式。
所以图片上传思路大致是:

  1. 监听一个input(type=‘file’)onchange事件,这样获取到文件file
  2. file转成dataUrl;
  3. 然后根据dataUrl利用canvas绘制图片压缩,然后再转成新的dataUrl
  4. 再把dataUrl转成Blob
  5. Blob appendFormData中;
  6. xhr实现上传。

手机兼容性问题

理想很丰满,现实很骨感。
实际上由于手机平台兼容性问题,上面这套流程并不能全都支持。
所以需要根据兼容性判断。

经过试验发现:

  1. 部分安卓微信浏览器无法触发onchange事件(第一步就特么遇到问题)
    这其实安卓微信的一个遗留问题。 查看讨论 解决办法也很简单:input标签 <input type=“file" name="image" accept="image/gif, image/jpeg, image/png”>要写成<input type="file" name="image" accept=“image/*”>就没问题了。
  2. 部分安卓微信不支持Blob对象
  3. 部分Blob对象appendFormData中出现问题
  4. iOS 8不支持new File Constructor,但是支持input里的file对象。
  5. iOS 上经过压缩后的图片可以上传成功 但是size是0 无法打开。
  6. 部分手机出现图片上传转换问题,请移步
  7. 安卓手机不支持多选,原因在于multiple属性根本就不支持。
  8. 多张图片转base64时候卡顿,因为调用了cpu进行了计算。
  9. 上传图片可以使用base64上传或者formData上传

上传思路修改方案

经过考虑,我们决定做兼容性处理:

clipboard.png

这里边两条路,最后都是File对象appendFormData中实现上传。

代码实现

首先有个html

<input type="file" name="image" accept=“image/*” onchange='handleInputChange'>

然后js如下:

// 全局对象,不同function使用传递数据
const imgFile = {};

function handleInputChange (event) {
    // 获取当前选中的文件
    const file = event.target.files[0];
    const imgMasSize = 1024 * 1024 * 10; // 10MB

    // 检查文件类型
    if(['jpeg', 'png', 'gif', 'jpg'].indexOf(file.type.split("/")[1]) < 0){
        // 自定义报错方式
        // Toast.error("文件类型仅支持 jpeg/png/gif!", 2000, undefined, false);
        return;
    }

    // 文件大小限制
    if(file.size > imgMasSize ) {
        // 文件大小自定义限制
        // Toast.error("文件大小不能超过10MB!", 2000, undefined, false);
        return;
    }

    // 判断是否是ios
    if(!!window.navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)){
   
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值