这一篇文章介绍的方法不算原创了,只是引用的别人的文章,加上自己的注释,因为接触php时间不长,所以尝试的东西比较多,自己加的注释也比较简单,php高手请略过。
我要用到远程下载图片,是在做微信公众平台开发中“微信墙”这个子任务时遇到的,该需求中需要显示用户的头像,对于一般订阅号来说,我们在服务端拿到用户发送的消息时,是无法获得用户的名字、头像路径等基本信息的,我想到的解决方法主要有二:
1. 自己建一个用户表,用来存储微信一般消息里包含的用户名(FromUserName)和该用户真实名字以及该用户fakeid的对应关系,,实验发现,用户的FromUserName是一个和用户、公众平台微信号有关的字符串,具体生成策略不清楚,同一个用户往不同公众号上发消息,FromUserName是不同的,而每一个用户则对应唯一的fakeid,根据用户的fakeid,可以拼出头像url的地址,在我们的服务端收到用户发送的消息的时候,检查本地用户表中是否存有该FromUserName用户的真实信息,如果有,直接保存该条消息,如果没有,则模拟登陆微信公众平台的后台,拉取最近的新消息列表,比对得知该用户的用户名和fakeid,对于服务号来说,微信提供了接口来获取用户头像,但对于普通订阅号,只能根据用户的fakeid来拿头像,而且,这个头像必须是已登录用户才能访问的,为了防止模拟登陆中session超时等一系列问题,我就在模拟登陆拉用户信息的时候,直接将他的头像下载到本地保存。
2. 另一种思路是,不在收到用户消息的时候触发模拟登陆微信号后台的操作,而是定时地去微信后台拉取数据,根据lastmsgid,将最新的消息存到本地数据库,当然存储用户信息的方式,和前文介绍的相同。
不管用哪一种思路(实际中我用的是第一种),我都需要远程下载用户头像,因为之前没有接触过php,这个需求的解决,就google来解决了,测试代码如下:
<?php function download($url, $cookie="", $file="", $timeout=60) { $file = empty($file) ? pathinfo($url, PATHINFO_BASENAME) : $file; $dir = pathinfo($file, PATHINFO_DIRNAME); !is_dir($dir) && @mkdir($dir,0755,true); $url = str_replace(" ","%20",$url); if(function_exists('curl_init')) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_COOKIE, $cookie); $temp = curl_exec($ch); if(@file_put_contents($file, $temp) && !curl_error($ch)) { return $file; } else { return false; } } else { $opts = array( "http"=>array( "method"=>"GET", "header"=>"", "timeout"=>$timeout) ); $context = stream_context_create($opts); if(@copy($url, $file, $context)) { //$http_response_header return $file; } else { return false; } } } $url = 'http://www.google.com.hk/images/srpr/logo11w.png'; echo download($url, '', $_SERVER['DOCUMENT_ROOT'] . '/Public/google.png');
该函数的四个参数,分别是要下载头像的url,cookie串,保存到哪个目录下(本机的绝对路径,使用$_SERVER['DOCUMENT_ROOT']获取Web根目录在本机的位置),请求超时时间,该代码的逐行解释如下:
// 如果没有指定保存路径,则把url中的文件名作为保存后的文件名 $file = empty($file) ? pathinfo($url, PATHINFO_BASENAME) : $file; // 如果没有指定保存路径,或指定了保存的文件名但没有目录,则使用当前目录'.',若指定了则使用指定目录 $dir = pathinfo($file, PATHINFO_DIRNAME); // 如果该目录不存在,则递归(第三个参数)创建该目录,权限为755,windows中,权限这个参数是被忽略的 // php中在函数名前+@来抑制函数的错误输出 !is_dir($dir) && @mkdir($dir, 0755, true); // 将url中的空格使用url编码来进行编码 $url = str_replace(" ","%20",$url);
如果启用了curl则执行以下代码,因为一般php都会开启curl,所以else里的代码我没有验证,在这里只说使用curl方法的,curl的方法在性能上要略优于file_get_contents:
// 初始化curl,指定目标url、超时时间、要求返回数据和cookie(a=111&b=222的形式) $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($ch, CURLOPT_COOKIE, $cookie); // 执行curl,拉取数据 $temp = curl_exec($ch); // 将返回的数据写入文件,如果写入的字节数不为0且curl未发生错误,则返回文件路径或文件名 if(@file_put_contents($file, $temp) && !curl_error($ch)) { return $file; }
至此,下载操作完成,该方法来源:PHP代码实现远程下载文件到本地的函数。