|
本篇文章给大家分享的内容是PHP+sftp实现的文件上传与下载,有着一定的参考价值,有需要的朋友可以参考一下最近开发一个与银行合作的项目,需要上传与下载文件。对文件保密有一定要求,所以用了SFTP。但实际开发中,遇到了很多问题,网上找的教程与案例都不能用,也是千遍一律的,复制来,复制去的。最后在不断的调试后终于实现了PHP的文件上传与下载。现记录下来,仅供参考。1.检查PHP版本,下载对应ssh2扩展,具体安装,麻烦网上搜索一下。phpinfo()检查是否安装好。安装成功后,可以看到ssh2.2.网上提供的上传下截方法(相信你肯定看到过)<·?·php//php环境中必须有ssh·$strServer="服务器ip"//服务器ip·$strServerPort="22"//端口号·$strServerUsername="***"//用户名·$strServerPassword="***"//密码·//connecttoserver·$resConnection=ssh2_connect($strServer,$strServerPort);·if(ssh2_auth_password($resConnection,$strServerUsername,$strServerPassword)){·//初始化SFTP·$resSFTP=ssh2_sftp($resConnection);·echo$resSFTP;·//下载文件·//1·$filename='D:down'time().'txt'·$opts=array(·'http'=>array(·'method'=>"GET"·'timeout'=>60,·)·);·$context=stream_context_create($opts);·$strData=·file_get_contents("ssh2.sftp://{$resSFTP}/var/testfile/abc.txt"false,$context);·file_put_contents($filename,$strData);·//2也可以用copy()·//if(!copy("ssh2.sftp://{$resSFTP}/dfr508/WUN/ikea-logo.jpg"$filename)){·//echo'downloadfailed'·//}·//--------------------------------------------------------------------------------------------------------------·//上传文件·//1·//file_put_contents("ssh2.sftp://{$resSFTP}/var/testfile/456.txt"'D:/ab.txt');·//2也可以用copy()·if(!copy("d:/ab.txt""ssh2.sftp://{$resSFTP}/var/testfile/up"time()."txt")){·echo'uploadfailed'·}·}else{·echo"无法在服务器进行身份验证"·}·?·>但是我自己按照网上的教程,怎么也实现不了,最后只好一步步排查原因。$strServer=""//服务器ip$strServerPort=""//端口号$strServerUsername=""//用户名$strServerPassword=""//密码//1连接服务器$resConnection=ssh2_connect($strServer,$strServerPort);//2验证连if(ssh2_auth_password($resConnection,$strServerUsername,$strServerPassword)){//3初始化SFTP$resSFTP=ssh2_sftp($resConnection);首先前面3步是没有问题的用copy,file_get_content,curl方法实现上传下载都报502错误。检查了路径等问题,也没问题,但就是不能成功。后面推断sftp服务器上的文件地址不能访问。"ssh2.sftp://{$resSFTP}/var/testfile/abc.txt"现在只有找到真正可用的地址才行,查看了很多资料,最后在PHP手册上找到了ssh2_sftp_realpath检查文件真实路径,最后返回连接上SFTP后访问文件的地址。传入"ssh2.sftp://{$resSFTP}/var/testfile/abc.txt"会报错,说明这个地址是错的。最后检查出上传,下载地址不需要加上前面的sh2.sftp://{$resSFTP}直接用SFTP文件路径。上传使用的函数也不能用前面提到的copy,file_get_content,curl需要用ssh2_scp_send上传ssh2_scp_recv下载用ASP实现无组件上传/下载文件功能简介将上传的文件数据保存到数据库中,可以处理表单中的多个上传文件的情况适用于各种数据库,使用ADO的方法连接数据库本示例中使用的是ACCESS数据库:zj.mdb表:tb_img(idint(自增列),pathtext(255)保存上传文件的目录,fnametext(250)保存上传的文件名,typetest(250)保存上传文件的类型,imgole对象保存上传的文件内容====================================================================================================================================上传文件的HTML页:zj_up.htm==================================================================代码如下:<html><head><title>文件上传保存到数据库中</title></head><body><formname=form1enctype=multipart/form-datamethod=postaction=zj_up.asp><p><inputtype=filename=file><inputtype=submitname=Submitvalue=上传></p></form></body></html>==================================================================上传文件保存到数据库的ASP页:zj_up.asp==================================================================代码如下:<%Response.Expires=0Functionf_Bin2Str(ByValsBin)DimiI,iLen,iChr,iReiRe=IfNotIsNull(sBin)TheniLen=LenB(sBin)ForiI=1ToiLeniChr=MidB(sBin,iI,1)IfAscB(iChr)>127TheniRe=iRe&Chr(AscW(MidB(sBin,iI+1,1)&iChr))iI=iI+1ElseiRe=iRe&Chr(AscB(iChr))EndIfNextEndIff_Bin2Str=iReEndFunctioniConcStr=Provider=Microsoft.Jet.OLEDB.4.0;PersistSecurityInfo=False&_;DataSource=&server.mappath(zj.mdb)iSql=tb_imgsetiRe=Server.CreateObject(ADODB.Recordset)iRe.OpeniSql,iConcStr,1,3iLen=Request.TotalBytessBin=Request.BinaryRead(iLen)iCrlf1=ChrB(13)&ChrB(10)iCrlf2=iCrlf1&iCrlf1iLen=InStrB(1,sBin,iCrlf1)-1iSpc=LeftB(sBin,iLen)sBin=MidB(sBin,iLen+34)iPos1=InStrB(sBin,iCrlf2)-1WhileiPos1>0iStr=f_Bin2Str(LeftB(sBin,iPos1))iPos1=iPos1+5iPos2=InStrB(iPos1,sBin,iSpc)iPos3=InStr(iStr,;filename=)+12IfiPos3>12TheniStr=Mid(iStr,iPos3)iPos3=InStr(iStr,Chr(13)&Chr(10)&Content-Type:)-2iFn=Left(iStr,iPos3)IfiFn<>TheniRe.AddNewire(path)=left(iFn,instrrev(iFn,))iRe(fname)=mid(iFn,instrrev(iFn,)+1)iRe(type)=Mid(iStr,iPos3+18)iRe(img).AppendChunkMidB(sBin,iPos1,iPos2-iPos1)iRe.UpdateEndIfEndIfsBin=MidB(sBin,iPos2+iLen+34)iPos1=InStrB(sBin,iCrlf2)-1WendiRe.closesetiRe=Nothing%>==================================================================下载数据的ASP页:zj_down.asp==================================================================代码如下:<%Response.Buffer=trueResponse.CleariConcStr=Provider=Microsoft.Jet.OLEDB.4.0;PersistSecurityInfo=False&_;DataSource=&server.mappath(zj.mdb)setiRe=server.createobject(adodb.recordset)iSql=tb_imgiRe.openiSql,iconcstr,1,1Response.ContentType=ire(type)Response.BinaryWriteiRe(img)iRe.closesetiRe=Nothing%>文件下载:html:下载1.rar下载1.jpg通过程序下载1.jpg下载nv.jpgphp处理:文件上传:html代码:php代码:common.func.phpupload.func1.php$val){$files[$i][name]=$file[name][$key];$files[$i][type]=$file[type][$key];$files[$i][tmp_name]=$file[tmp_name][$key];$files[$i][error]=$file[error][$key];$files[$i][size]=$file[size][$key];$i++;}}}return$files;}/***针对于单文件、多个单文件、多文件的上传*@paramarray$fileInfo*@paramstring$path*@paramstring$flag*@paramnumber$maxSize*@paramarray$allowExt*@returnstring*/functionuploadFile($fileInfo,$path=./uploads,$flag=true,$maxSize=1048576,$allowExt=array(jpeg,jpg,png,gif)){//$flag=true;//$allowExt=array(jpeg,jpg,gif,png);//$maxSize=1048576;//1M//判断错误号if($fileInfo[error]===UPLOAD_ERR_OK){//检测上传得到小if($fileInfo[size]>$maxSize){$res[mes]=$fileInfo[name].上传文件过大;}$ext=getExt($fileInfo[name]);//检测上传文件的文件类型if(!in_array($ext,$allowExt)){$res[mes]=$fileInfo[name].非法文件类型;}//检测是否是真实的图片类型if($flag){if(!getimagesize($fileInfo[tmp_name])){$res[mes]=$fileInfo[name].不是真实图片类型;}}//检测文件是否是通过HTTPPOST上传上来的if(!is_uploaded_file($fileInfo[tmp_name])){$res[mes]=$fileInfo[name].文件不是通过HTTPPOST方式上传上来的;}if($res)return$res;//$path=./uploads;if(!file_exists($path)){mkdir($path,0777,true);chmod($path,0777);}$uniName=getUniName();$destination=$path./.$uniName...$ext;if(!move_uploaded_file($fileInfo[tmp_name],$destination)){$res[mes]=$fileInfo[name].文件移动失败;}$res[mes]=$fileInfo[name].上传成功;$res[dest]=$destination;return$res;}else{//匹配错误信息switch($fileInfo[error]){case1:$res[mes]=上传文件超过了PHP配置文件中upload_max_filesize选项的值;break;case2:$res[mes]=超过了表单MAX_FILE_SIZE限制的大小;break;case3:$res[mes]=文件部分被上传;break;case4:$res[mes]=没有选择上传文件;break;case6:$res[mes]=没有找到临时目录;break;case7:case8:$res[mes]=系统错误;break;}return$res;}}doAction5.php;$uploadFiles[]=$res[dest];}$uploadFiles=array_values(array_filter($uploadFiles));print_r($uploadFiles);上面是通过函数实现,下载封装成为类:html:upload.class.phpfileName=$fileName;$this->maxSize=$maxSize;$this->allowMime=$allowMime;$this->allowExt=$allowExt;$this->uploadPath=$uploadPath;$this->imgFlag=$imgFlag;$this->fileInfo=$_FILES[$this->fileName];}/***检测上传文件是否出错*@returnboolean*/protectedfunctioncheckError(){if(!is_null($this->fileInfo)){if($this->fileInfo[error]>0){switch($this->fileInfo[error]){case1:$this->error=超过了PHP配置文件中upload_max_filesize选项的值;break;case2:$this->error=超过了表单中MAX_FILE_SIZE设置的值;break;case3:$this->error=文件部分被上传;break;case4:$this->error=没有选择上传文件;break;case6:$this->error=没有找到临时目录;break;case7:$this->error=文件不可写;break;case8:$this->error=由于PHP的扩展程序中断文件上传;break;}returnfalse;}else{returntrue;}}else{$this->error=文件上传出错;returnfalse;}}/***检测上传文件的大小*@returnboolean*/protectedfunctioncheckSize(){if($this->fileInfo[size]>$this->maxSize){$this->error=上传文件过大;returnfalse;}returntrue;}/***检测扩展名*@returnboolean*/protectedfunctioncheckExt(){$this->ext=strtolower(pathinfo($this->fileInfo[name],PATHINFO_EXTENSION));if(!in_array($this->ext,$this->allowExt)){$this->error=不允许的扩展名;returnfalse;}returntrue;}/***检测文件的类型*@returnboolean*/protectedfunctioncheckMime(){if(!in_array($this->fileInfo[type],$this->allowMime)){$this->error=不允许的文件类型;returnfalse;}returntrue;}/***检测是否是真实图片*@returnboolean*/protectedfunctioncheckTrueImg(){if($this->imgFlag){if(!@getimagesize($this->fileInfo[tmp_name])){$this->error=不是真实图片;returnfalse;}returntrue;}}/***检测是否通过HTTPPOST方式上传上来的*@returnboolean*/protectedfunctioncheckHTTPPost(){if(!is_uploaded_file($this->fileInfo[tmp_name])){$this->error=文件不是通过HTTPPOST方式上传上来的;returnfalse;}returntrue;}/***显示错误*/protectedfunctionshowError(){exit(.$this->error.);}/***检测目录不存在则创建*/protectedfunctioncheckUploadPath(){if(!file_exists($this->uploadPath)){mkdir($this->uploadPath,0777,true);}}/***产生唯一字符串*@returnstring*/protectedfunctiongetUniName(){returnmd5(uniqid(microtime(true),true));}/***上传文件*@returnstring*/publicfunctionuploadFile(){if($this->checkError()&&$this->checkSize()&&$this->checkExt()&&$this->checkMime()&&$this->checkTrueImg()&&$this->checkHTTPPost()){$this->checkUploadPath();$this->uniName=$this->getUniName();$this->destination=$this->uploadPath./.$this->uniName...$this->ext;if(@move_uploaded_file($this->fileInfo[tmp_name],$this->destination)){return$this->destination;}else{$this->error=文件移动失败;$this->showError();}}else{$this->showError();}}}doAction6.phpuploadFile();echo$dest;
|