发送邮件请求以复制文件并获得进度响应

时间:2013-10-25 15:41:39

标签: php jquery

发送使用以下代码复制文件的发布请求

 $.ajax({
     url:filename,
     type: 'post',
     dataType: 'html',
     data: {"data":someData}, 
     success: function(data) {
       console.log(data);
       alert(data);
     },
     error:function(err){
      console.log(err);
     }
   });

以下功能复制文件并给我进度

function copyfiles($filename,$filesize){
    $remote = fopen('../filestorage/'.$filename, 'r');
    $local = fopen('../uploads/'.$filename, 'w');
    $read_bytes = 0;
    while(!feof($remote)) {
      $buffer = fread($remote, 2048);
      fwrite($local, $buffer);
      $read_bytes += 2048;
      $progress = min(100, 100 * $read_bytes / $filesize);
  echo json_encode(array("progress"=>$progress));
    }
   fclose($remote);
   fclose($local);
}

但我得到的是下面的一个回复

        {"progress":16.956449743335}{"progress":33.91289948667} 
         {"progress":50.869349230005}{"progress":67.82579897334}
         {"progress":84.782248716675}{"progress":100}

我希望逐个获取,然后显示复制的进度。   请建议我该怎么做。

2 个答案:

答案 0 :(得分:4)

实现这一目标的一种方法是拥有两个服务(或php页面等)。一个服务(s1)可能是您已接受请求并开始复制的服务。其他服务(s2)可能正在响应正在复制的每个文件的状态。为了实现这一点,您需要考虑以下因素

  1. 服务s1应立即响应开始复制的ID或文件名

  2. 虽然复制进度应保存在地图中,其中文件的键映射到进度值(记住用户可能需要复制多个文件)

  3. 客户端应不断调用服务s2获取进度值,将参数作为参数传递

  4. 服务s2应查看该地图并使用所请求文件密钥的进度进行响应

  5. 服务和地图可以轻松地与客户端的http会话一起工作/存储,以便准确地为多个客户端提供服务。可以选择其他存储方法,我认为http会话对于这种情况来说是最直接和最恰当的。

    修改

    这是php中的一个演示应用程序,其中服务s1正在http会话中写入,服务s2正在从中读取。您的代码留在注释中,以显示您可以放置​​新代码的位置。

    <强> HTML / JS

    <body>
            <div>
                <input type="radio" name="file" value="file1" />file1
                <br/>
                <input type="radio" name="file" value="file2" />file2
                <br/>
                <input type="radio" name="file" value="file3" />file3
                <br/>
                <input type="radio" name="file" value="file4" />file4
                <br/><br/>
                <input type="button" value="copy files" />
                <br/><br/>
                <div class="output"></div>
            </div>
            <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
            <script>window.jQuery || document.write('<script src="jquery-1.10.1.min.js"><\/script>')</script>
            <script>
                var progressInterval;
                $('input[type=button]').on('click',function(){
                    var filename = $('input:checked').val();
                    if(!filename)return;
                    $.ajax({
                        url:'service-copy-file.php',
                        type: 'post',
                        data: {"filename":filename},
                        dataType:'json',
                        success: function(data) {
                            console.log(data);
                            if(progressInterval) {
                                clearInterval(progressInterval);
                            }
                        },
                        error:function(err){
                            console.log(err);
                            if(progressInterval) {
                                clearInterval(progressInterval);
                            }
                        }
                    });
    
                    progressInterval = setInterval(function(){
                        $.ajax({
                            url:'service-progress.php',
                            type: 'get',
                            data: {"filename":filename},
                            dataType:'json',
                            success: function(data) {
                                console.log(data);
                                $('.output').text((parseInt(data.progress))+"%");
                            },
                            error:function(err){
                                console.log(err);
                            }
                        });
    
                    }, 1000);
    
                });
    
    
    
            </script>
        </body>
    

    服务s1

    <?php
    
    copyfiles($_POST['filename'], null);
    
    function copyfiless($filename, $filesize) {
        echo json_encode('copying ' . $filename);
    }
    
    function copyfiles($filename, $filesize) {
        // $remote = fopen('../filestorage/'.$filename, 'r');
        // $local = fopen('../uploads/'.$filename, 'w');
        // $read_bytes = 0;
        //emulate copying of a file for 10secs
        $fileKey = $filename;
        $progress = 0;
    
        $_SESSION[$fileKey] = $progress;
        // while(!feof($remote)) {
        while ($progress < 100) {
            session_start();
            //  $buffer = fread($remote, 2048);
            //  fwrite($local, $buffer);
            //  $read_bytes += 2048;
            //  $progress = min(100, 100 * $read_bytes / $filesize);
            //  echo json_encode(array("progress"=>$progress));
    
            sleep(2); //emulate copying
            $progress+=10;
            $_SESSION[$fileKey] = $progress;
            session_write_close();
        }
        session_start();
        unset($_SESSION[$fileKey]); //completed copy
        // fclose($remote);
        // fclose($local);
    }
    
    ?>
    

    服务s2

    <?php
    
    session_start();
    
    getProgress($_GET['filename']);
    
    function getProgress($filename) {
        if (isset($_SESSION[$filename])) {
            echo json_encode(array("progress" => $_SESSION[$filename]));
        } else {
            echo json_encode(array("progress" => -1));
            // echo json_encode('could not find file:'.$filename);
        }
    }
    
    ?>
    

    这将实时复制您的文件。但是,如果您想从服务器获得响应而不必从客户端进行轮询,那么您需要使用HTTP服务器推送,这需要更多的努力来实现。

答案 1 :(得分:1)

我唯一一次这样做是在4年前。不知道它是否会对你有所帮助,但那是我的系统:

  1. 在进行长时间处理(不仅仅是文件传输)时,用于执行此操作的PHP必须将进程存储到文件(或mysql db ...)中,不要忘记关闭文件(如果你选择文件)阅读权利!

  2. 在此过程中,回调(现在在ajax,但它是我的自动刷新)调用一个PHP函数,返回读取文件(或db)的当前进程值

  3. 跳它会有帮助!