嗨,在我的php应用程序中,我想使用stream_copy_to_stream

时间:2015-11-29 22:48:04

标签: php

在我的php应用程序中我想使用“stream_copy_to”从互联网上下载文件,但由于文件可能很长,我想在javascript进度条中保持跟踪进度。我怎样才能做到这一点 ?有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您可以将事件数据存储在数据库表中,并且在复制运行时,您可以向php脚本发出AJAX请求以返回进度:

  1. 将文件总大小与当前文件大小进行比较(方法 如下所述)。
  2. 不使用stream_copy_to_stream而是使用循环一次复制小块,定期更新数据库中的bytes_received列
  3. 一般方法

    在启动stream_copy_to_stream之前,您将获得Content-Length标头(如果可用)并将其存储在数据库表或其他表中以供将来比较。

    执行stream_copy_to_stream时,对php脚本使用AJAX请求,将输出文件大小与内容长度进行比较,并返回进度条中使用的百分比。

    $sourceFile = 'your-source-file';
    $destFile = 'your-destination-file-name';
    $source = fopen($sourceFile, 'r'); 
    $headers = parseHeaders(stream_get_meta_data($source)['wrapper_data']);
    if ($headers['response_code'] == 200 && isset($headers['Content-Length']))
    {
        // insert $destFile, $headers['Content-Length'] into database
        // return the ID to frontend for progress checks
    }
    $dest = fopen($destFile, 'w');
    stream_copy_to_stream($source, $dest);
    

    您可以使用此类函数来解析标题

    function parseHeaders($headers)
    {
        $head = array();
        foreach( $headers as $k=>$v )
        {
            $t = explode(':', $v, 2);
            if (isset($t[1] ))
                $head[trim($t[0])] = trim($t[1]);
            else
            {
                $head[] = $v;
                if(preg_match("#HTTP/[0-9\.]+\s+([0-9]+)#",$v,$out))
                    $head['reponse_code'] = intval($out[1]);
            }
        }
        return $head;
    }
    

    前端您将触发AJAX请求以启动副本,该请求将返回ID和Content-Length信息以设置进度条。

    当副本运行时,会在一段时间内触发一个AJAX请求来检查进度并更新进度条。

    // get the file information from the database based on the ID
        // $totalSize = Content-Length data from database
    $currentSize = filesize($destFile);
    $progress = min(100, 100 * $currentSize / $totalSize);
    echo json_encode(array('progress' => $progress));