Chinaunix
标题:
JIEQI CMS 之远程FTP附件上传改造
[打印本页]
作者:
徐风
时间:
2009-03-20 10:49
标题:
JIEQI CMS 之远程FTP附件上传改造
通常网站数据中,图片或者附件下载总是特别耗服务器资源的。所以大型网站都采用了附件和网页分服务器的方法。
从网站程序考虑,要把附件上传到独立服务器,一种方法是提交的时候直接提交到附件的服务器上,这样的话附件服务器需要有程序接受和处理程序。另一种常用方法是附件先提交到程序所在服务器,然后程序服务器用ftp功能把文件再传到附件服务器。对大部分用户来说,第二种方法会更简单点,至少附件服务器不用专门装个web程序了。
JIEQI CMS在考虑ftp远程附件上传功能支持的时候,为了兼顾之前版本的升级,尽量不对以前程序和使用方式做大的改动。因此统一设计了一个ftp类和文件上传处理函数,同时支持普通的上传和传到ftp远程,这里的区别这是在参数设置上下功夫
JIEQI CMS里面对上传类文件的保存目录参数有三种写法
1、仅填目录名,如 attachment ,则附件保存在网站 /files/modname/attachment 目录(这里的 modname 是指模块标记,如 system、article、forum)
2、填完整的路径名,如 E:/web/attachment 则附件保存在这个目录下(这种情况,附件的访问url需要人工设置)
3、保存到ftp远程服务器上,路径设置采用ftp的url写法,如
ftp://user:pass@www.domain.com/files/attachment
,则上传的附件程序自动通过ftp传到对应服务器目录下(这种情况,附件的访问url需要人工设置)
代码1:文件拷贝函数,支持普通文件拷贝和ftp拷贝,主要在上传附件后使用
/**
* 拷贝或者移动文件
*
* @param string $from_file 原始文件名
* @param string $to_file 拷贝到文件名,支持ftp模式,如 [url=ftp://user:password@host/dir/file.txt]ftp://user:password@host/dir/file.txt[/url]
* @param int $mode 保存后的文件权限
* @param bool $move 是否移动文件,默认false表示拷贝,true表示移动
* @access public
* @return bool 成功返回true,失败返回false
*/
function jieqi_copyfile($from_file, $to_file, $mode = 0777, $move = false){
$from_file = trim($from_file);
if(!is_file($from_file)) return false;
$to_file = trim($to_file);
$matches = array();
if(!preg_match('/^(ftps?):\/\/([^:\/]+):([^:\/]*)@([0-9a-z\-\.]+)(:(\d+))?([0-9a-z_\-\/\.]*)/is', $to_file, $matches)){
jieqi_checkdir(dirname($to_file), true);
if(is_file($to_file)) @unlink($to_file);
if($move) $ret = rename($from_file, $to_file);
else $ret = copy($from_file, $to_file);
if($ret && $mode) @chmod($to_file, $mode);
return $ret;
}else{
include_once(JIEQI_ROOT_PATH.'/lib/ftp/ftp.php');
$ftpssl = (strtolower($matches[1]) == 'ftps') ? 1 : 0;
$matches[6]=intval(trim($matches[6]));
$ftpport = ($matches[6] > 0) ? $matches[6] : 21;
$ftp =& JieqiFTP::getInstance($matches[4], $matches[2], $matches[3], '.', $ftpport, 0, $ftpssl);
if(!$ftp) return false;
$matches[7] = trim($matches[7]);
if(!$ftp->ftp_chdir(dirname($matches[7]))){
if(substr($matches[7],0,1) == '/') $matches[7] = substr($matches[7],1);
$pathary = explode('/', dirname($matches[7]));
foreach ($pathary as $v){
$v=trim($v);
if(strlen($v) > 0){
if($ftp->ftp_mkdir($v) !== false && $mode) $ftp->ftp_chmod($mode, $v);
$ftp->ftp_chdir($v);
}
}
}
$ret = $ftp->ftp_put(basename($matches[7]), $from_file);
if($ret && $mode) $ftp->ftp_chmod($mode, basename($matches[7]));
$ftp->ftp_close();
if($move) @unlink($from_file);
return $ret;
}
}
复制代码
代码2:文件删除函数,支持本地文件和ftp文件,在删除附件时候用
/**
* 删除文件
*
* @param string $file_name 文件名
* @access public
* @return bool 成功返回true,失败返回false
*/
function jieqi_delfile($file_name){
$file_name = trim($file_name);
$matches = array();
if(!preg_match('/^(ftps?):\/\/([^:\/]+):([^:\/]*)@([0-9a-z\-\.]+)(:(\d+))?([0-9a-z_\-\/\.]*)/is', $file_name, $matches)){
return @unlink($file_name);
}else{
include_once(JIEQI_ROOT_PATH.'/lib/ftp/ftp.php');
$ftpssl = (strtolower($matches[1]) == 'ftps') ? 1 : 0;
$matches[6]=intval(trim($matches[6]));
$ftpport = ($matches[6] > 0) ? $matches[6] : 21;
$ftp =& JieqiFTP::getInstance($matches[4], $matches[2], $matches[3], '.', $ftpport, 0, $ftpssl);
if(!$ftp) return false;
$matches[7] = trim($matches[7]);
return $ftp->ftp_delete($matches[7]);
}
}
复制代码
代码3:ftp类,通用的ftp处理
<?php
/**
* FTP操作类
*
* 定义FTP相关功能
*
* 调用模板:无
*
* @category jieqicms
* @package system
* @copyright Copyright (c) Hangzhou Jieqi Network Technology Co.,Ltd. ([url=http://www.jieqi.com]http://www.jieqi.com[/url])
* @author $Author: juny $
* @version $Id: [url=ftp://ftp.php]ftp.php[/url] 318 2009-01-09 04:58:56Z juny $
*/
/**
* FTP类
*
* @category jieqicms
* @package system
*/
class JieqiFTP extends JieqiObject{
var $_host; //服务器
var $_port = 21; //端口
var $_user; //用户名
var $_pass; //密码
var $_path = '.'; //默认路径
var $_ssl = 0; //是否使用SSL连接
var $_timeout = 0; //连接超时
var $_pasv = 1; //是否被动模式
var $connid; //连接字符串
/**
* 去掉换行符
*
* @param string $str
* @access public
* @return string
*/
function wipespecial($str) {
return str_replace(array("\n", "\r"), '', $str);
}
/**
* 构造函数,设置ftp基本参数
*
* @param string $ftphost ftp服务器地址
* @param string $ftpuser 用户名
* @param string $ftppass 密码
* @param string $ftppath 默认路径
* @param int $ftpport 端口号
* @access private
* @return void
*/
function JieqiFTP($ftphost = '', $ftpuser = '', $ftppass = '', $ftppath = '.', $ftpport = 21, $timeout = 0, $ftpssl = 0, $ftppasv = 1){
$this->_host = $this->wipespecial($ftphost);
$this->_user = $ftpuser;
$this->_pass = $ftppass;
$this->_port = intval($ftpport);
$this->_timeout = intval($timeout);
$this->_ssl = intval($ftpssl);
$this->_pasv = intval($ftppasv);
$this->_path = $ftppath;
}
/**
* 返回静态实例变量的引用
*
* @param void
* @access private
* @return array
*/
function &retInstance(){
static $instance = array();
return $instance;
}
/**
* 关闭所有ftp连接
*
* @param void
* @access public
* @return bool
*/
function close($ftp = NULL) {
if(is_object($ftp)){
$ftp->ftp_close();
}else{
$instance =& JieqiFTP::retInstance();
if(!emptyempty($instance)){
foreach($instance as $ftp){
$ftp->ftp_close();
}
}
}
}
/**
* 创建一个实例,如果已经存在则直接返回
*
* @param string $ftphost ftp服务器地址
* @param string $ftpuser 用户名
* @param string $ftppass 密码
* @param string $ftppath 默认路径
* @param int $ftpport 端口号
* @access private
* @return void
*/
function &getInstance($ftphost = '', $ftpuser = '', $ftppass = '', $ftppath = '.', $ftpport = 21, $timeout = 0, $ftpssl = 0, $ftppasv = 1){
$instance =& JieqiFTP::retInstance();
$inskey = md5($ftphost.','.$ftpuser.','.$ftppass.','.$ftppath.','.$ftpport.','.$timeout.','.$ftpssl.','.$ftppasv);
if (!isset($instance[$inskey])) {
$instance[$inskey] = new JieqiFTP($ftphost, $ftpuser, $ftppass, $ftppath, $ftpport, $timeout, $ftpssl, $ftppasv);
$fid = $instance[$inskey]->ftp_connect();
if(!$fid) return false;
}
return $instance[$inskey];
}
/**
* ftp链接
*
* @param void
* @access public
* @return int
*/
function ftp_connect() {
[url=]//@set_time_limit(0[/url]);
$func = $this->_ssl && function_exists('ftp_ssl_connect') ? 'ftp_ssl_connect' : 'ftp_connect';
if($func == 'ftp_connect' && !function_exists('ftp_connect')) {
$this->raiseError('FTP not supported', JIEQI_ERROR_RETURN);
return -4; //不支持ftp函数
}
if($this->connid = @$func($this->_host, $this->_port, 20)) {
if($this->_timeout && function_exists('ftp_set_option')) {
@ftp_set_option($this->connid, FTP_TIMEOUT_SEC, $this->_timeout);
}
if($this->ftp_login($this->_user, $this->_pass)) {
if($this->_pasv) {
$this->ftp_pasv(TRUE);
}
if($this->ftp_chdir($this->_path)) {
if(!defined('JIEQI_FTP_CONNECTED')) @define('JIEQI_FTP_CONNECTED',true);
return 1;
} else {
$this->ftp_close();
$this->raiseError('Chdir '.$this->_path,' error', JIEQI_ERROR_RETURN);
return -3; //设置目录失败
}
} else {
$this->ftp_close();
$this->raiseError('FTP login failure', JIEQI_ERROR_RETURN);
return -2; //登录失败
}
} else {
$this->raiseError('Couldn\'t connect to '.$this->_host.':'.$this->_port, JIEQI_ERROR_RETURN);
return -2; //连接失败
}
}
/**
* 新建目录
*
* @param string $directory
* @access public
* @return bool
*/
function ftp_mkdir($directory) {
$directory = $this->wipespecial($directory);
return @ftp_mkdir($this->connid, $directory);
}
/**
* 删除目录
*
* @param string $directory
* @access public
* @return bool
*/
function ftp_rmdir($directory) {
$directory = $this->wipespecial($directory);
return @ftp_rmdir($this->connid, $directory);
}
/**
* 上传文件
*
* @param string $remote_file 远程文件名
* @param string $local_file 本地文件名
* @param int $mode 传输方式
* @param int $startpos 开始位置
* @access public
* @return bool
*/
function ftp_put($remote_file, $local_file, $mode = FTP_BINARY, $startpos = 0 ) {
$remote_file = $this->wipespecial($remote_file);
$local_file = $this->wipespecial($local_file);
$mode = intval($mode);
$startpos = intval($startpos);
return @ftp_put($this->connid, $remote_file, $local_file, $mode, $startpos);
}
/**
* 取得ftp服务器上文件大小
*
* @param string $remote_file
* @access public
* @return int
*/
function ftp_size($remote_file) {
$remote_file = $this->wipespecial($remote_file);
return @ftp_size($this->connid, $remote_file);
}
/**
* 关闭ftp连接
*
* @param void
* @access public
* @return bool
*/
function ftp_close() {
return @ftp_close($this->connid);
}
/**
* 删除文件
*
* @param string $path
* @access public
* @return bool
*/
function ftp_delete($path) {
$path = $this->wipespecial($path);
return @ftp_delete($this->connid, $path);
}
/**
* 下载文件
*
* @param string $local_file 本地文件名
* @param string $remote_file 远程文件名
* @param int $mode 传输方式
* @param int $resumepos 开始位置
* @access public
* @return bool
*/
function ftp_get($local_file, $remote_file, $mode = FTP_BINARY, $resumepos = 0) {
$remote_file = $this->wipespecial($remote_file);
$local_file = $this->wipespecial($local_file);
$mode = intval($mode);
$resumepos = intval($resumepos);
return @ftp_get($this->connid, $local_file, $remote_file, $mode, $resumepos);
}
/**
* ftp登录
*
* @param string $username 用户名
* @param string $password 密码
* @access public
* @return bool
*/
function ftp_login($username, $password) {
$username = $this->wipespecial($username);
$password = str_replace(array("\n", "\r"), array('', ''), $password);
return @ftp_login($this->connid, $username, $password);
}
/**
* 主动还是被动模式
*
* @param int $pasv
* @access public
* @return bool
*/
function ftp_pasv($pasv) {
$pasv = intval($pasv);
return @ftp_pasv($this->connid, $pasv);
}
/**
* 改变路径
*
* @param string $directory
* @access public
* @return bool
*/
function ftp_chdir($directory) {
$directory = $this->wipespecial($directory);
return @ftp_chdir($this->connid, $directory);
}
/**
* 向服务器发送 SITE 命令
*
* @param string $cmd
* @access public
* @return bool
*/
function ftp_site($cmd) {
$cmd = $this->wipespecial($cmd);
return @ftp_site($this->connid, $cmd);
}
/**
* 改变文件权限
*
* @param int $mode 访问权限
* @param string $filename 文件名
* @access public
* @return bool
*/
function ftp_chmod($mode, $filename) {
$mode = intval($mode);
$filename = $this->wipespecial($filename);
if(function_exists('ftp_chmod')) {
return @ftp_chmod($this->connid, $mode, $filename);
} else {
return $this->ftp_site($this->connid, 'CHMOD '.$mode.' '.$filename);
}
}
/**
* 文件重命名
*
* @param string $oldfile 原文件名
* @param string $newfile 新文件名
* @access public
* @return bool
*/
function ftp_rename($oldfile, $newfile) {
return @ftp_rename($this->connid, $oldfile, $newfile);
}
/**
* 获得当前路径
*
* @param void
* @access public
* @return string
*/
function ftp_pwd() {
return @ftp_pwd($this->connid);
}
/**
* 返回给定目录的文件列表
*
* @param string $path
* @access public
* @return array
*/
function ftp_nlist($path) {
$path = $this->wipespecial($path);
return @ftp_nlist($this->connid, $path);
}
/**
* 删除FTP文件夹及里面文件
*
* @param string $path
* @param bool $flag true表示删除目录本身(默认),false表示清空目录里面内容
* @access public
* @return bool
*/
function ftp_delfolder($path, $flag = true) {
$path = $this->wipespecial($path);
if($flag) $ret = $this->ftp_rmdir($path) || $this->ftp_delete($path);
else $ret = false;
if (!$ret){
$files = $this->ftp_nlist($path);
foreach ($files as $values){
$values = basename($values); //有的FTP服务器ftp_nlist()返回的是路径+文件名形式的数组
if(!$this->ftp_delete($path .'/'. $values)){
$this->ftp_delfolder($path .'/'. $values, true);
}
}
if($flag) return $this->ftp_rmdir($path);
else return true;
}else{
return $ret;
}
}
/**
* 根据给定路径字符串,循环创建目录(当前目录下创建)
*
* @param string $path
* @access public
* @return bool
*/
function ftp_mkdirs($path)
{
$path = $this->wipespecial($path);
$path_arr = explode('/',$path); // 取目录数组
$path_div = count($path_arr); // 取层数
foreach($path_arr as $val) // 创建目录
{
if($this->ftp_chdir($val) == FALSE)
{
$tmp = $this->ftp_mkdir($val);
if($tmp == FALSE)
{
$this->raiseError('FTP mkdir failure', JIEQI_ERROR_RETURN);
exit;
}
$this->ftp_chdir($val);
}
}
for($i=1;$i<=$path_div;$i++) // 回退到根(创建时的目录)
{
@ftp_cdup($this->connid);
}
}
}
?>
复制代码
本文首发及存档:
http://www.xufeng.org/?action=show&id=36
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2