【问题标题】:send post request to copy file and get progress response发送发布请求以复制文件并获取进度响应
【发布时间】:2013-10-25 15:41:39
【问题描述】:

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

 $.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}

我要一个一个的拿到,然后显示复制了多少的进度。 请建议我该怎么做。

【问题讨论】:

  • 是的。好的,你能告诉我我该怎么做吗?

标签: php jquery


【解决方案1】:

实现此目的的一种方法是拥有两个服务(或 php 页面等)。一项服务 (s1) 可能是您已经拥有的服务,它接受请求并开始复制。另一个服务 (s2) 可能会响应每个正在复制的文件的状态。为了使其正常工作,您需要考虑以下事项

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

  2. 在复制进度时,应将文件的键映射到进度值的映射中(记住用户可能需要复制多个文件)

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

  4. 服务 s2 应该查看该映射并以请求的文件密钥的进度进行响应

服务和地图可以很容易地与客户端的 http 会话一起工作/存储,以便准确地为多个客户端提供服务。可以选择其他存储方法,我认为 http session 是最直接和最适合这种情况的。

编辑

这是一个 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 服务器推送,这需要更多的努力来实现。

【讨论】:

  • @melc 感谢您的回复。我尝试了客户端调用服务 s1 进行复制的方式。此服务还调用服务 s2 中的方法来设置进度值。一旦我发送请求来复制文件,我也会向服务 s2 发送请求以获取进度响应,但得到的是空结果。如果我错过了什么,你能告诉我吗
  • @nyfer s1 应该将进度值存储在一个数组中,其中的键是文件名或唯一的东西,并用进度值或只是最后一个进度值来赋值一个数组。然后将数组存储在用户会话中,w3schools.com/php/php_sessions.asp。无需从 s1 请求 s2。当客户端使用从 s1 返回的文件名键调用 s2 时,s2 应该检查会话并返回进度。如果您确实需要,我会尝试在当天发布一些代码。
  • @melc 谢谢。检查这个链接,看看我是怎么做到的stackoverflow.com/questions/19605009/…
  • @melc 是的 melc 你能把它贴出来吗,我真的需要它。我试图让它工作,但不知何故它不起作用。我们也可以实时获取进度而不是存储在会话中然后检索它吗?
  • @nyfer 通过演示实现编辑了答案,希望对您有所帮助。
【解决方案2】:

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

  1. 在进行长时间处理(不仅仅是文件传输)时,PHP 过去必须将进程存储到文件(或 mysql db...)中,不要忘记关闭文件(如果您选择一个文件)以获得阅读权限!

  2. 在此期间,回调(现在在 ajax,但对我来说是自动刷新)调用 PHP 函数,该函数返回读取文件(或 db)的当前进程值

希望它会有所帮助!

【讨论】:

    猜你喜欢
    • 2011-07-06
    • 1970-01-01
    • 2023-02-01
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 1970-01-01
    • 2020-10-05
    • 1970-01-01
    相关资源
    最近更新 更多