最近接了一个需求,需要做上传,框架用多了,本来以为这些东西拿过来直接用就行,但是在开发过程中发现了一些问题:
一、安卓手机上传图片没有拍照选项、ios没有拍照选择相册功能
1、按照以下方式写安卓手机没有拍照选项,只能传图片
1 | <input type="file" name="pic" id="pic" accept="image/gif, image/jpeg" /> |
2、按照以下方式写ios手机正常,有选择图片和拍照上传功能,安卓手机大部分没有问题,但是安卓10版本没有拍照上传功能
1 | <input type="file" id="choose" accept="image/*" multiple> |
3、按照以下方式写ios手机直接唤起拍照功能,没有选择图片上传功能,(安卓10版本预计可以拍照上传)
1 | <input type="file" id="choose" accept="image/*" capture="camera" multiple> |
accept表示打开的系统文件目录
capture表示的是系统所捕获的默认设备,
camera:照相机;camcorder:摄像机;microphone:录音;
其中还有一个属性multiple,支持多选,当支持多选时,multiple优先级高于capture,所以只用写成:
二、优化上传图片增加图片上传压缩功能
用canvas压缩图片的原理就是读取图片的文件,然后把图片画在画布上,再用canvas自带的一个接口:
1 | canvas.toDataURL(type,encoderOptions); |
第二个参数encoderOptions决定了图片压缩的程度,可以在0-1中选择一个值,当然推荐不要低于0.5,因为这样保存后的图片质量不太好。
这个方法执行完后会返回一个值,就是图片的base64格式的字符串,这个字符串就可以上传到服务端。
三、移动端IOS系统手机拍照图片Canvas压缩上传后图片旋转的bug
网上大部分是说exfe.js来读取图片信息,我们上传的图片里面是有很多信息的
这里我们需要拿到Orientation的值有1,3,6,8之类的,分别代表0°,180°,顺时针90°,逆时针90°
图片原文
1 | //获取照片方向角属性,用户旋转控制 |
但是,这里正常是我拿到角度之后绘制图片按照角度回正,大部分机器是没有问题的,安卓手机测试了下,什么角度拍照Orientation都为1,IOS的Orientation都是按照角度返回的,但是在IOS13.4版本以后,带有角度上传的图片也不会旋转,所以需要版本号判断IOS13.4以后不做回正处理
1 | let iosVersion = UserAgent.str.match(/CPU iPhone OS (.*?) like Mac OS/); |
1 | const canvas = document.createElement('canvas'); |
四、前端上传图片利用canvas水印合成
大体步骤:
用户使用input file上传图片的时候,利用 FileReader ,读取 blob对象 ,或者是 file对象 ,将图片转化为 data uri (base64格式)的形式。
使用 canvas ,在页面上新建一个画布,利用 canvas 提供的API,将图片画入这个画布当中。
利用 canvas.toDataURL() ,进行图片的压缩,得到图片的 data uri 的值,用来上传。
获取到压缩后的base64格式图片数据,转成二进制塞入formdata,再通过XmlHttpRequest提交formdata。