使用curl恢复ftp上传

时间:2013-11-30 15:16:45

标签: php curl upload ftp resume

我正在建立一个php脚本,将大型文件从本地php服务器上传到远程ftp服务器,并在mysql库中记录进度。 Evrything工作正常,但我的恢复功能有问题,我找不到任何关于恢复ftl上传与curl的过程的明确信息。我的代码如下:

$fp = fopen($localfile, 'r');

curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_NOPROGRESS, false);
curl_setopt($curl, CURLOPT_PROGRESSFUNCTION, 'curlProgressCallback'); // lof progress to base
curl_setopt($curl, CURLOPT_READFUNCTION, 'curlAbortCallback'); // check if user request abort

curl_setopt($curl, CURLOPT_URL, $ftp);
curl_setopt($curl, CURLOPT_PORT, FTPPort);
curl_setopt($curl, CURLOPT_LOW_SPEED_LIMIT, 1000);
curl_setopt($curl, CURLOPT_LOW_SPEED_TIME, 20); 
curl_setopt($curl, CURLOPT_USERPWD, FTPLog . ":" . FTPPass);
curl_setopt($curl, CURLOPT_FTP_CREATE_MISSING_DIRS, true); 
curl_setopt($curl, CURLOPT_UPLOAD, 1);

if($resume){
    $startFrom=ftpFileSize($dest); // return the actual file size on the ftp server
}else{         
    $startFrom=false;        
}

if($startFrom){ 
    curl_setopt ($curl, CURLOPT_FTPAPPEND, 1);
    curl_setopt($curl, CURLOPT_RESUME_FROM, $startFrom);       
    fseek($fp, $startFrom, SEEK_SET);
    $sizeToUp=filesize($localfile);//-$startFrom;        
}else{               
    $sizeToUp=filesize($localfile);
}    
curl_setopt($curl, CURLOPT_INFILE, $fp);
curl_setopt($curl, CURLOPT_INFILESIZE, $sizeToUp);

curl_exec($curl); 

如果有人打电话给我这方面的帮助,或者重定向我一个有效的例子,那将非常有帮助和欣赏。

提出反馈意见

先生

3 个答案:

答案 0 :(得分:0)

我不认为cURL& PHP可以做到这一点。

您使用的是Linux吗?如果是这样看看aria2。它支持可恢复连接并支持FTP。我不确定它是否会完全符合您的要求。

答案 1 :(得分:0)

所以我中止了我的研究,用卷曲制作简历,而不是帮助或文件, 使用ftp_nb_put来实现它真的更容易。所以我可以帮助别人,你可以找到我的最终代码的例子:

    define("FTPAdd","your serveur ftp address");                                    
    define("FTPPort",21);                                                           
    define("FTPTimeout",120);
    define("FTPLog","your login");                                                 
    define("FTPPass","your password"); 

    function ftpUp_checkForAndMakeDirs($ftpThread, $file) {
            $parts = explode("/", dirname($file));
            foreach ($parts as $curDir) {            
                if (@ftp_chdir($ftpThread, $curDir) === false) { // Attempt to change directory, suppress errors
                    ftp_mkdir($ftpThread, $curDir); //directory doesn't exist - so make it
                    ftp_chdir($ftpThread, $curDir); //go into the new directory
                }
            }
    }   
    function ftpUp_progressCallBack($uploadedData){
         global $abortRequested;
         //you can do any action you want while file upload progress, personaly, il log progress in to data base
         //and i request DB to know if user request a file transfert abort and set the  var $abortRequested to true or false
    }
    function ftpUp($src,$file,$dest,$resume){
            global $abortRequested; 

            $conn_id = ftp_connect(FTPAdd,FTPPort,FTPTimeout);
                if ($conn_id==false){
                        echo "FTP Connection problem";return false;                
                }else{
                        $login_res = ftp_login($conn_id, FTPLog, FTPPass);
                        if ($login_res){
                                $ftpThread=$conn_id;            
                        }else{
                                echo "FTP Authentification error";return false;
                        }
                }
            $fp = fopen($src, 'r');     

            ftpUp_checkForAndMakeDirs($ftpThread, $dest); //verif et creation de l'arborescence sur le serveur ftp
            ftp_set_option ($ftpThread, FTP_AUTOSEEK, TRUE); // indispensable pour pouvoir faire du resume

            if($resume){            
                $upload = ftp_nb_fput ($ftpThread, $file, $fp ,FTPUpMode, FTP_AUTORESUME);
            }else{
                $upload = ftp_nb_fput ($ftpThread, $file, $fp ,FTPUpMode);    
            }       
            ///////////////////////////////////////////////////////////////////////////////////
            //uploading process
            while ($upload == FTP_MOREDATA) {               
                //progress of upload                
                    ftpUp_progressCallBack(ftell ($fp));                
                //continue or abort 
                if(!$abortRequested){
                    $upload = ftp_nb_continue($ftpThread);
                }else{              
                    $upload = "userAbort";
                }            
             }
             ///////////////////////////////////////////////////////////////////////////////////
             //end and result                   
             ftpUp_progressCallBack(ftell ($fp));       

             if ($upload != FTP_FINISHED) {
                 @fclose($fp);
                 @ftp_close ($ftpThread);
                 if ($abortRequested){                              
                    echo "FTP Abort by user : resume needed";
                 }else{
                    echo "FTP upload error : ".$upload." (try resume)";
                 }
             }else{
                @fclose($fp);
                @ftp_close ($ftpThread);
                echo "upload sucess";
             }

    } 


    $file="test.zip";
    $src = "FilesToUp/" . $file; 
    $destDir = "www/data/upFiles/";
    $dest = $destDir . $file;
    $abortRequested=false;

    ftpUp($src,$file,$dest,true);

答案 2 :(得分:0)

我正在寻找一个可行的答案,使用CURL + PHP来恢复被破坏的传输,并且无法在互联网上找到明确,可行的解决方案。这是一个老问题,但我认为它确实需要一个正确的答案。这是一两天研究的结果。请参阅以下功能和快速使用示例。

连接功能:

function ftp_getconnect($uName, $pWord, $uHost)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_USERPWD, "$uName:$pWord");
    curl_setopt($ch, CURLOPT_URL, $uHost);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $return = curl_exec($ch);
    if($return === false)
    {
        print_r(curl_getinfo($ch));
        echo curl_error($ch);
        curl_close($ch);
        die('Could not connect');
    }
    else
    {
        return $ch;
    }
}

断开连接功能:

function ftp_disconnect($ch)
{
    $return = curl_close($ch);
    if($return === false)
    {
        return "Error: Could not close connection".PHP_EOL;
    }
    else
    {
        return $return;
    }
}

获取远程文件大小的函数(以字节为单位):

function get_rem_file_size($ch, $rem_file)
{
    curl_setopt($ch, CURLOPT_INFILE, STDIN);
    curl_setopt($ch, CURLOPT_URL, $rem_file);
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_HEADER, true);
    curl_setopt($ch, CURLOPT_FTP_CREATE_MISSING_DIRS, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_FTPLISTONLY, false);
    $return = curl_exec($ch);
    if($return === false)
    {
        print_r(curl_getinfo($ch));
        echo curl_error($ch);
        curl_close($ch);
        die('Could not connect');
    }
    else
    {
        $file_header = curl_getinfo($ch);
        return $file_header['download_content_length'];
    }
}

上传文件功能:

function upload_file($ch,$local_file,$remote_file,$resume)
{
    echo "attempting to upload $local_file to $remote_file".PHP_EOL;
    $file = fopen($local_file, 'rb');
    if($resume)
    {
        curl_setopt($ch, CURLOPT_RESUME_FROM, get_rem_file_size($ch, $remote_file));
    }
    curl_setopt($ch, CURLOPT_URL, $remote_file);
    curl_setopt($ch, CURLOPT_UPLOAD, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FTP_CREATE_MISSING_DIRS, true);
    curl_setopt($ch, CURLOPT_INFILE, $file);
    curl_setopt($ch, CURLOPT_INFILESIZE, filesize($local_file));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $return = curl_exec($ch);

    if($return === false)
    {
        fclose($file);
        return curl_error($ch).PHP_EOL;
    }
    else
    {
        fclose($file);
        echo $local_file.' uploaded'.PHP_EOL;
        return true;
    }
}

快速使用示例:

$ftp = ftp_getconnect($uName, $pWord, 'ftp://'.$uHost);

$rem_file = 'ftp://'.$uHost.'/path/to/remote/file.ext';
$loc_file = 'path/to/local/file.ext';
$resume = 'true';
$success = upload_file($ftp, $loc_file, $rem_file, $resume);
if($success !== true)
{
    //failure
    echo $success;
    curl_close($ch);
}
print_r(ftp_disconnect($ftp));

快速注意,如果有大量文件,您可以循环浏览它们upload_file,而无需每次连接/断开连接。