前端 input 手机上传图片的坑

4,717 阅读3分钟

前端上传图片,一般是用 Web 原生的 input 去调用手机系统的相册(文件)或者摄像头拍照,最近开发遇到两个坑

1. 怎么控制可以选择手机拍照模式还是从相册/文件里面选取文件?

我们的需求很简单,只需限制上传图片类型,并且可以使用手机拍照和从相册选取。

其实是通过下面三点控制的

  1. type = 'file'
  2. accept="image/*"(mime)
  3. capture

先仔细读一读 mdn 再读一读 w3c

最后看完还是云里雾里,因为 input=“type” 太依赖系统了,在每个系统上的体现多多少少都会有差异,上面 w3c 有几个 demo 也都是 PC 端的,并没有移动端。

一开始,理想很丰满,想一步到位,直接由系统去判断。

<input type="file" accept="image/jpeg,image/jpg,image/png,application/pdf" onchange="change" capture="camera"/> 

然而实际操作中,ios正常,android 可能只有拍照,不能从文件系统中选取文件。 后来经过尝试,选择了折衷方案,只需要做如下改动即可,(不需要加 capture)

<input type="file" accept="image/*" onchange="change"/> 
// 具体的控制图片类型,在 change 中拿到 file 对象时候,交给 js 去控制

额外的点是,安卓手机在微信环境内打开地址,图片多选功能是失效的,只能一张一张上传。需要多选功能要去使用微信的 sdk

2. iphone 和 android 系统提示的图片大小和 change 事件中获取到的 file.size 的大小不一致。

当我们使用 file.size 去判断图片大小的时候会发现,安卓好像有轻微误差,iphone 大于 3m 的图片会有误差,甚至一张 7mb 的图片,file.size可能是 3mb

jsfiddle 测试地址

当时通过反复测试,也没测出来啥,但突然想到苹果图片格式是 heic 图片格式,会不会与这个有关,然后再网上下载了一张 6mb 的 jpg 图片发送到 iphone 上来上传,发现 file.size 就是正常的 6mb,破案了。

这个问题,实际上就是手机系统计算图片大小的方式不一样

  1. 拿了几台 android 试了下,有些图片是按照 1000km = 1mb 而不是 1024 kb = 1mb,
  2. 苹果是因为,拍照的时候苹果默认使用 heic 格式存储图片,上传的时候系统可能会做转换和压缩

如果想在上传的时候,看到的 文件大小和上传的限制大小一致,可以设置。 iphone 图片格式

其他

其实还遇到个问题,目前没解决,部分老旧的 vivo 手机,微信扫描二维码进入页面(或者扫码进入页面再手动刷新浏览器),然后调用摄像头或者图册,点击确认选择之后,微信浏览器页面直接退出了,但是如果不是二维码进入,而是直接点击链接进入,微信浏览器就不会闪退,如果知道解决方案的朋友,麻烦分享下解决方法咯,感谢,一起进步!