New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
移动端Web上传图片实践 #7
Comments
感謝分享,這是大坑啊。有一次我们遇到这个问题怪异的哭笑不得。 |
这个坑终于看到解决方案了。大赞! |
感谢 分享 |
用的是插件吗?是什么插件 |
移动端不知道可否一次上传多张图片? |
粘贴剪切板的时候如何实现图片上传呢? |
找到解决方案了,感谢大牛 |
@kujian 我也想知道这个问题,有的手机能多张上传,有的不行。 |
这个问题可以用这个库解决 https://github.com/think2011/localResizeIMG
图片扭曲、某些设备不自动旋转图片方向,没有jpeg压缩算法.. 原生JS编写,不依赖例如jquery等第三方库,支持AMD or CMD规范。 |
@kujian 手机端可以一次上传多张图片的。把他们都往formdata里面塞,服务端接收一下,循环拿出来就可以了。 |
你好,最近在实践移动端图片上传,读您的文章受益匪浅,感谢,另有问题请教: 是否存在可能上传图片时,只能上传图片库里的图片而不能选择拍照呢? |
web前端层面做不到, 需要android ios提供对应的指令,然后把图片的base64给过来。 |
@Jerret321 感谢,我先问问客户端同事 |
有没有提高性能的呢?是不是使用translate3D开启之后可以加快绘制速度?最近在调使用input上传图片,使用canvas压缩,第二步就是将拍好的照片重新绘制,第三步又增加了按钮,旋转的按钮,PC端做好了,放到手机端(1)图片出不来(2)绘制速度超慢,平均一张图需要5s以上?有没有好的解决方法 |
移动端上传图片坑还是挺多的。 比如楼主还没有列出的 还有部分安卓机下不支持 说多了都是泪. |
gif图过大 手机黑屏碰到过吗? |
1024 |
从iOS 6+、Android 3+开始 (来源http://mobilehtml5.org/),移动端可以通过网页中的
<input type="file">
来拍照上传或是上传相册中的照片。 不过从图片上传到服务器后可能会遇到图片莫名其妙旋转的问题,如图一些设备在拍照时明明是竖着拍的(右),传到服务端后从图片查看器中看到的是横着的(左),而在一些图片处理工具或是浏览器中通过http协议看到的却是正常的,原因是在照片的exif中的Orientation属性控制了照片的旋转方向。
大部分图片查看器和编辑工具都会去根据这个属性控制照片方向,而windows自带的查看器等工具并不理睬他。
为什么要有Orientation属性呢,我并没有找到官方的解释,见到种说法挺有道理:几乎所有的摄像头在出场的时候成相芯片都是有方向的,拍出来的照片的像素都是默认方向的。如果每拍一张照片就对这些像素进行旋转,如果数码相机每秒连拍20张来算,旋转操作将会非常耗时。更聪明的做法是拍照时只记录一个方向,然后显示的时候按方向显示出来即可。因此exif定义了一个标准的方向参数,只要读图的软件都来遵守规则,加载时候读取图片方向,然后做相应的旋转即可。这样既可以达到快速成像的目的,又能达到正确的显示。
修正图片方向的问题
为了图片显示不出问题,我们得修改Orientation属性。首先想到的是服务端来修正方案,对于图片来说exif信息不是必须的,可以根据Orientation的值来对照片进行手动矫正的操作,然后再去掉exif,类似这样:
更好的方式是用一些图片工具自动处理,GraphicsMagick和Imagemagick用来处理这个再合适不过了,他俩都可以用对图像进行旋转、裁剪、缩放、替换颜色;添加文本、水印、图形等常见操作,GraphicsMagick是从Imagemagick分支出来的,他俩有着几乎一样的API,可以在命令行工具中轻松操作。这里我用的是GraphicsMagick,他更轻便,易装易用。在Java、PHP、Nodejs等常见后端语言中可以用相关库轻松的操作GraphicsMagick的API。
后端以Nodejs为例。首先你需要在你的机器上安装GraphicsMagick。 然后npm install gm 模块就可以了。gm提供的接口非常友好,你只要
这样就已经完成了图片的自动修正方向和压缩尺寸的工作。
异步上传图片
传统提交表单方式放在今天已经不能忍了,XHR2中支持把文件放在Formdata对象中异步提交,只考虑移动端,就可以舍弃iframe之类的兼容方案了。核心代码这样:
XHR2中还可以通过process事件来监听进度,实现类似进度条的功能
用FormData发送的请求头中你的Content-Type 会变成这样 multipart/form-data; boundary=----WebKitFormBoundaryyqVkWF3PcCpAzZp9,如果上传时要附带参数也可以直接append到formData里。
然后Nodejs中可以用connect-busboy来接收文件,在express框架中大概是这样:
前端压缩图片
图片上传的主体工作算是完成了,不过现在手机随便拍张照片就是一两兆,wifi环境下不说,移动网络通过这方案上传照片就有点坑了。手机客户端中一般会先压缩图片再上传,Web中如何实现压缩后上传呢?
可以把图片读到canvas中,然后用canvas.toDataURL()接口输出画布的base64编码,再把base64编码转成Blob塞到Formdata里传到后端。这样即可以压缩图片减少流量,又可以在前端就修正图片旋转的问题。(Discuss:直接把base64传到后端是否可行呢,后面试一试)
canvasResize这个库已经把一切封装好了https://github.com/gokercebeci/canvasResize ,同时他依赖Exif.js 修正了因Orientation属性产生的旋转问题。前端主要的代码:
Nodejs中代码可以参考前面的,继续用connect-busboy模块接收文件。
实际测试一下iOS没问题,Android 4 有些机型不行,貌似修改过file的Blob数据发到服务端的数据字节就会为0 这是安卓的bug https://code.google.com/p/android/issues/detail?id=39882 。 网上有人给出的解决方案是用FileReader把文件读出来,然后把整个二进制文件当请求发到服务端,这种方式要附带参数的话只能放url里了。
后端在接收这些数据时,会是一段一段的,我是用的拼接的方式处理
实测一下,稍低端的的安卓上有点卡,毕竟处理一张图片的运算量可不小,目测目前用前端压缩上传方案的不多,至少微博触屏版 (http://m.weibo.cn/) 就是把原始图片直接上传的,这种方式是否适合直接使用或者还有哪些可以优化的地方有待验证。
这里有一个完整的demo https://github.com/xiangpaopao/mobile-upload-demo 包括上面提到的两种方案
使用的话,依次安装GraphicsMagick > npm install > node app.js
参考
The text was updated successfully, but these errors were encountered: