php中本地文件拷贝至远程服务器的实现方式

需要解决的问题:本地文件搬移至远程服务器

前提:在linux服务器之间拷贝

以下作为备忘和整理记录下来

因为在linux上拷贝文件,同事提醒用scp来做,搜索php scp之后发现php官方提供了使用scp向远程服务器拷贝文件以及相应的ssh连接方法。

使用方法如下:

$ip = XXX;
$port = XXX;
$user = XXX;
$pass = XXX;
$material_path = 'material_api.txt';
$target_path = '/data/aa/a';
$connection = ssh2_connect($ip, $port);
ssh2_auth_password($connection, $user, $pass);
$sftp = ssh2_sftp($connection);
$result = ssh2_scp_send($connection, $material_path, $target_path."/".$material_path, 0777);
echo "拷贝文件结果".$result."\n";
 
 
 测试以上方法,报错 
Call to undefined function ssh2_connect()


检查需要在服务器上安装ssh扩展,需要libssh2、ssh2。

安装扩展之后,测试上面代码成功。


实际需要拷贝的文件是视频文件,于是换为视频文件。

程序报错

Failed copying file

多次尝试都失败,换为demo中的txt文件,执行成功。

猜测是文件类型或文件大小的原因。

找了一个小的视频文件,发现可以拷贝,文件大小增大之后,同样报错:Failed copying file

查看文件系统,复制的文件大小小于实际文件。

查看官方网站的说明,没有对ssh2_scp_send方法的传输文件的大小的说明。

再查网上只找到一个类似情况的提问,说遇到大文件的时候,拷贝文件失败。

后来在php官网看到用户贡献的使用方法中提到使用fopen、fwrite作为替代,方法如下:

<?php
$srcFile = '/var/tmp/dir1/file_to_send.txt';
$dstFile = '/var/tmp/dir2/file_received.txt';

// Create connection the the remote host
$conn = ssh2_connect('my.server.com', 22);

// Create SFTP session
$sftp = ssh2_sftp($conn);

$sftpStream = @fopen('ssh2.sftp://'.$sftp.$dstFile, 'w');

try {

    if (!$sftpStream) {
        throw new Exception("Could not open remote file: $dstFile");
    }
    
    $data_to_send = @file_get_contents($srcFile);
    
    if ($data_to_send === false) {
        throw new Exception("Could not open local file: $srcFile.");
    }
    
    if (@fwrite($sftpStream, $data_to_send) === false) {
        throw new Exception("Could not send data from file: $srcFile.");
    }
    
    fclose($sftpStream);
                    
} catch (Exception $e) {
    error_log('Exception: ' . $e->getMessage());
    fclose($sftpStream);
}
?>
测试小文件方法可用,100+MB的视频也可以拷贝,300+MB的视频同样不能拷贝成功,但没有错误信息。

后来在程序中打上log,发现拷贝大文件的时候程序执行到@file_get_contents($srcFile)就不向下执行,但也没有错误信息。

猜测file_get_contents()方法将文件内容读为一个字符串,当文件大小比较大时,方法处理时会有问题。

同事提醒php中有原生的执行命令的方法,可以试试直接使用命令拷贝文件。方法如下:

$user = XXX;
$ip = XXX;
$source_path= 'material_api.txt';
$target_path = '/data/aa/a';
$dest = $user."@".$ip.":".$target_path."/".$source_path;
exec("scp ".$source_path." ".$dest , $output, $return);
 方法使用spc命令直接向远程服务器拷贝文件。 

测试上述代码发现执行时,需要身份验证。

再通过资料查找建立了server1和server2之间的信任关系,使server1向server2执行scp不再需要每次都输入密码。

再测试以上代码,当拷贝成功的时候$return=0;失败的时候$return=1,完成了本地文件向远程服务器拷贝文件的要求。


ps:后期查找资料发现,对于file_get_contents(filename, use_iclude_path,context,offset,maxlen)读取大文件时,也许能够通过参数offset(文件读取的起始位置)、maxlen(读取的最大长度)的设置来分段读取文件。

如何在server1和server2之间建立信任关系不在这里说明,会另外说明。




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
data\bbscache文件 ftpserver.php 放在程序对应的文件里面 修改文件列表:(PHP文件6个,HTML文件1个) job.php,read.php,show.php,setforum.php,postupload.php,template.php,setforum.htm 1. 数据库升级 进入phpMyAdmin -> SQL 下运行下面升级 ALTER TABLE `pw_forums` ADD `remoteftp` INT( 3 ) UNSIGNED DEFAULT '0' NOT NULL ; ALTER TABLE `pw_attachs` ADD `remoteftp` INT( 3 ) UNSIGNED DEFAULT '0' NOT NULL ; 2. job.php ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆找到require_once('global.php'); ◆下面加入 //远程ftp修改by axing include_once(D_P.'data/bbscache/ftpserver.php'); //远程ftp修改by axing ◆找到 if(!$attach_url && !is_readable("$attachdir/$attachurl")){ Showmsg('job_attach_error'); } ◆替换成 //远程ftp if(!$attach_url && !is_readable("$attachdir/$attachurl") && !$remoteftp){ Showmsg('job_attach_error'); } //远程ftp ◆找到 if($attach_url && !file_exists("$attachdir/$attachurl") && function_exists('file_get_contents')){ $downcontent=file_get_contents($attach_url."/$attachurl"); ◆替换成 if(($attach_url && !file_exists("$attachdir/$attachurl") && function_exists('file_get_contents'))||$remoteftp){ //远程ftp by axing if($remoteftp) { $downcontent=file_get_contents($ftplist[$remoteftp][url]."/$attachurl"); }else{ $downcontent=file_get_contents($attach_url."/$attachurl"); } //远程ftp by axing ◆找到 P_unlink("$attachdir/$attachurl"); ◆替换成 //远程ftp by axing if($remoteftp) { del_ftp_attach($remoteftp,$attachurl); }else { P_unlink("$attachdir/$attachurl"); } //远程ftp by axing 3. read.php ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆找到 require_once(R_P.'require/bbscode.php'); ◆下面加入 //远程ftp修改by axing include_once(D_P.'data/bbscache/ftpserver.php'); //远程ftp修改by axing ◆找到 if ($groupid != 3 && !$foruminfo['allowvisit'] && (!$foruminfo['forumadmin'] || strpos($foruminfo['forumadmin'],','.$windid.',')===false)){ ◆替换成 if ($windid != $manager && $groupid != 3 && !$foruminfo['allowvisit'] && (!$foruminfo['forumadmin'] || strpos($foruminfo['forumadmin'],','.$windid.',')===false)){ ◆找到 $db_signwindcode,$fid,$tid,$pid, ◆后面加入 $remoteftp,$ftplist, ◆找到 $a_url=$attachpath.'/'.$at['attachurl']; ◆下面加入 //远程ftp修改 by axing } elseif($at['remoteftp']){ $a_url=$ftplist[$at['remoteftp']][url].'/'.$at['attachurl'];//远程的图片地址 //远程ftp修改 by axing 4. show.php ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆找到 include_once(D_P.'data/bbscache/forum_cache.php'); ◆下面加入 //远程ftp include_once(D_P.'data/bbscache/ftpserver.php'); //远程ftp ◆找到 a.descrip, ◆后面加入(有两处都要记得改) a.remoteftp, ◆找到 } else{ continue; } ◆上面加入 //远程ftp } elseif($rt['remoteftp']){ $rt['a_url']=$ftplist[$rt['remoteftp']][url].'/'.$rt['attachurl']; //远程ftp ◆找到 } }else{ Showmsg('pic_not_exists'); ◆上面加入 //远程ftp } elseif($rt['remoteftp']){ $rt['a_url']=$ftplist[$rt['remoteftp']][url].'/'.$rt['attachurl']; //远程ftp 5. admin/setforum.php ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆找到 include_once(D_P.'data/bbscache/forumcache.php'); ◆下面加入 //远程ftp修改 by axing include_once("./data/bbscache/ftpserver.php");//引入FTP服务器列表 //远程ftp修改 by axing ◆找到 $viewdownload =str_replace("_{$value}_",'checked',$viewdownload); ◆下面加入 //远程ftp修改 $ftpselected[$remoteftp]='selected'; $ftpselect="<option value=0>本地空间</option>"; foreach($ftplist as $ftpinfo){ $ftpid=$ftpinfo[id]; $ftpselect.="<option value=$ftpinfo[id] $ftpselected[$ftpid]>$ftpinfo[name]</option>"; } //远程ftp修改by axing ◆找到 ifhide='".(int)$ifhide."' ◆后面插入 ,remoteftp='$remoteftp' 6. require/postupload.php ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆找到 !function_exists('readover') && exit('Forbidden'); ◆下面加入 //远程ftp上传修改 by axing include_once(D_P.'data/bbscache/ftpserver.php'); //远程ftp上传修改 by axing ◆找到 $fileuplodeurl= $savedir.'/'.$fileuplodeurl; } ◆替换成 } //远程ftp修改 by axing if($foruminfo['remoteftp']){ $remoteftpid=$foruminfo['remoteftp']; $result = ftpconnect($ftplist[$remoteftpid]); ftp_cdup($result); if($db_attachdir){ if(!@ftp_chdir($result,$savedir)){ ftp_mkdir($result,$savedir); ftp_chdir($result,$savedir); } $attach_fname0=$fileuplodeurl; $fileuplodeurl= $savedir.'/'.$fileuplodeurl; }else{ $attach_fname0=$fileuplodeurl; } //$db->query("INSERT INTO pw_ftperror (attachment, ftpdate, ftpid) VALUES ('$fileuplodeurl', '$timestamp','$foruminfo[remoteftp]')"); //$attid = $db->insert_id(); if(@ftp_put($result, $attach_fname0, $atc_attachment, FTP_BINARY)){ //上传文件 $size=ceil(ftp_size($result,$attach_fname0)/1024); ftp_close($result); // $db->query("delete from pw_ftperror where aid = $attid"); }else{ showmsg('附件远程上传失败!');//远程上传失败 } }else{ //远程ftp修改 by axing $fileuplodeurl= $savedir.'/'.$fileuplodeurl; ◆找到 Showmsg('upload_content_error'); } ◆下面加入 //远程 ftp $size=ceil(filesize("$attachdir/$fileuplodeurl")/1024); } //远程 ftp ◆找到 $size=ceil(filesize("$attachdir/$fileuplodeurl")/1024); $atc_attachment_name=addslashes($atc_attachment_name); $db->update("INSERT INTO pw_attachs SET fid='$fid',uid='$winduid',hits=0,name='$atc_attachment_name',type='$type',size='$size',attachurl='$fileuplodeurl',needrvrc='$needrvrc',uploadtime='$timestamp',descrip='$descrip'"); ◆替换成 $atc_attachment_name=addslashes($atc_attachment_name); //远程ftp $db->update("INSERT INTO pw_attachs SET fid='$fid',uid='$winduid',hits=0,name='$atc_attachment_name',type='$type',size='$size',attachurl='$fileuplodeurl',needrvrc='$needrvrc',uploadtime='$timestamp',descrip='$descrip',remoteftp='$foruminfo[remoteftp]'"); //远程ftp ◆找到 'desc' => str_replace('\\','',$descrip) ◆下面加入 'remoteftp' => $foruminfo[remoteftp] 6.2 如果需要用到txt附件上传时,自动切割并依次上传功能,上面第6步不用修改,直接上传压缩包的postupload_txt.php 到require/目录即可. 并结合这个插件进行使用.https://blog.csdn.net/viqecel/article/details/79440688 7. require/template.php ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆找到 include_once(D_P."data/bbscache/forumcache.php"); ◆下面加入 //远程ftp include_once(D_P.'data/bbscache/ftpserver.php'); //远程ftp ◆找到 $a_url="$db_bbsurl/$attachpath/$at[attachurl]"; ◆下面加入 //远程ftp }elseif($at['remoteftp']){ $a_url=$ftplist[$at['remoteftp']][url].'/'.$at['attachurl']; //远程ftp 8. template/admin/setforum.htm ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ ◆找到 <tr class=b> <td><input type="checkbox" name="otherforum[logo]" value="1"></td> <td>版块图标</td> <td><input type="text" size="30" name="logo" value="$logo"></td> </tr> ◆下面加入 <tr class=b> <td><input type="checkbox" name="otherforum[remoteftp]" value="1"></td> <td>是否开启远程附件上传</td> <td><select name="remoteftp">$ftpselect</select></td> </tr> (完成...)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值