发现需求
最近在做一个项目,需要在微信里打开的网页中实现上传,IOS通过简单的上传插件可轻松搞定,但无论是FLASH+PHP还是JS+PHP,安卓平台微信内置浏览器始终无法上传文件。百度谷歌,均没有解决方案,参看很多公众平台的解决方案,多为推荐安卓用户跳到外部浏览器打开网页,但是这样体验不太好,于是着手自己去解决这个问题!再后来,听朋友说微信微社区可正常上传图片,于是去研究其上传代码,研究发现:
微社区在客户端用了一套比较高端的JS框架,该框架将图片进行data:image/jpg;base64编码并ajax的方式传输到服务端,并返回图片的photoid等相关信息。服务器端我是看不到处理的细节,不过大概了解,无非就是对图片进行存储和数据库插入等操作。于是copy下该上传方式的前端代码。再结合SAE Storage的相关API写了一个上传处理的php文件,就很快解决了这个问题,效果不错,部分低端部分手机有闪退现象,这个微社区也存在这种问题。魅族,三星等主流机型均完美上传,现在来和大家分享分享。
解决方案
1.SAE Storage
Storage -> 新建domain并命名为 imagefile,直接点击创建。
2.找到Storage的API http://apidoc.sinaapp.com/sae/SaeStorage.html
upload (line 291)
将文件上传入存储
注意:文件名左侧所有的'/'都会被过滤掉。
-
return: 写入成功时返回该文件的下载地址,否则返回false
-
author: Elmer Zhang
-
access: public
-
string $domain: 存储域,在在线管理平台.storage页面可进行管理
-
string $destFileName: 目标文件名
-
string $srcFileName: 源文件名
-
array $attr: 文件属性,可设置的属性请参考 SaeStorage::setFileAttr() 方法
-
bool $compress: 是否gzip压缩。如果设为true,则文件会经过gzip压缩后再存入Storage,常与$attr=array('encoding'=>'gzip')联合使用
write (line 251)
将数据写入存储
注意:文件名左侧所有的'/'都会被过滤掉。
-
return: 写入成功时返回该文件的下载地址,否则返回false
-
author: Elmer Zhang
-
access: public
-
string $domain: 存储域,在在线管理平台.storage页面可进行管理
-
string $destFileName: 文件名
-
string $content: 文件内容,支持二进制数据
-
int $size: 写入长度,默认为不限制
-
array $attr: 文件属性,可设置的属性请参考 SaeStorage::setFileAttr() 方法
-
bool $compress: 是否gzip压缩。如果设为true,则文件会经过gzip压缩后再存入Storage,常与$attr=array('encoding'=>'gzip')联合使用
这里有两个函数可用,一个是upload,另一个是write,经实测,用upload直接处理编码过的图片会报错,应该需要先用PHP中的 base64_decode()函数解码再用write函数写入sae storage上刚才新建的imagefile里。
3.服务器端的处理代码如下:
PHP代码
-
<?php
-
//感谢@韩文博1学长的代码精炼建议
-
$ex = explode(",",$_POST['pic']);//分割data-url数据
-
$filter=explode('/', trim($ex[0],';base64'));//获取文件类型
-
$s = base64_decode(str_replace($filter[1] , '', $ex[1]));//图片解码
-
-
$picname = date("YmdHis") . rand(100, 999) .'.'.$filter[1];//生成随机文件名
-
-
$s = new SaeStorage();//实例化SeaStorage类
-
$photo_id = $s->write("imagefile",$picname,$ss);//把解码后的图片写入创建的imagefile里,成功返回图片的url
-
-
if($photo_id){ //返回json数据到浏览器端
-
$status='success';
-
$errCode='0';
-
$arr = array(
-
'photo_id'=>$photo_id,
-
'status'=>$status,
-
'errCode'=>$errCode);
-
echo json_encode($arr);
-
}
-
-
-
?>
4.前端上传代码登录微社区,找到发帖功能,自行chrome工具下载前端代码。
修改相应的服务器端响应文件(见图中选取的部分)
5.拓展阅读
Data URL是在本地直接绘制图片,不是从服务器加载,所以节省了HTTP连接,起到加速网页的作用。
语法:
data:image/jpg; 声明数据协议及类型名称
base64, 编码形式为base64
/9j/4AAQSkZ…… base64编码结果
附上Data URL的生成方法(PHP):
PHP代码
-
<?php
-
-
$img_file = file_get_contents("http://tieba.baidu.com/tb/static-common/img/dimensionCode/tb_common_2dbc.jpg");
-
-
echo base64_encode($img_file);
-
-
?>
用这种方法会加重客户端的CPU和内存负担,总之有利有弊。 针对于一些小的数据,可以在网页中直接嵌入,而不是从外部文件载入,比如图片。这样的好处是可以减少一次http的请求,缺点是使得页面内容变大。data类型的url格式在98年就已经提出了,现在绝大部分的浏览器都能支持,比如使用IE6内核的国内浏览器,chrome和firefox等,实测安卓和ios上的微信浏览器均兼容此方案。大家有什么疑问,微博私信我http://weibo.com/itjaye