通过 HTTP 以 1k 块的形式传输任何类型的文件

问题描述

我需要通过 HTTP/GET 以大约 1k 块的形式传输任何类型或大小的文件生成文件哈希需要与源文件匹配。这需要在原生 PHP 中完成,无需任何特殊工具。我有一个基本的策略,但我得到了奇怪的结果。这个概念证明只是在本地复制文件

代码

<?PHP

    $input="/home/lm1/Music/Ellise - Feeling Something Bad.mp3";
    $a=pathinfo($input);
    $output=$a["basename"];

    echo "\n> ".md5_file($input);
    $fp=fopen($input,'rb');

    if ($fp) {

        while(!feof($fp)) {
            $buffer=base64_encode(fread($fp,1024));
            // echo "\n\n".md5($buffer);
            write($output,$buffer);
        }
        fclose($fp);
        echo "\n> ".md5_file($output);
        echo "\n";
        
    }   
    
    function write($file,$buffer) { 
        // echo "\n".md5($buffer);
        $fp = fopen($file,'ab');
        fwrite($fp,base64_decode($buffer));
        fclose($fp);    
    }   
    
?>

输出

> d31e102b1cae9c73bbf5a12615a8ea36
> 9f03f6c88ed61c07cb534922d6d31864

提前致谢。

解决方法

fread 已经提前了文件指针的位置,所以没有必要跟踪它。与 frwite 相同,因此连续调用会自动附加到给定文件。因此,您可以简化您的方法(改编自 this answer 的关于如何有效地将大型输入流写入文件的代码):

$src  = "a.test";
$dest = "b.test";

$fp_src = fopen($src,'rb');

if ($fp_src) {
    
    $fp_dest     = fopen($dest,'wb');
    $buffer_size = 1024;

    while(!feof($fp_src)) {
        
        fwrite($fp_dest,fread($fp_src,$buffer_size));
    }

    fclose($fp_src);
    fclose($fp_dest);

    echo md5_file($src)."\n";  // 88e4af2f85080a280e7f00e50d96b7f7
    echo md5_file($dest)."\n"; // 88e4af2f85080a280e7f00e50d96b7f7
}

如果您想将两个进程分开,您可以这样做:

$src  = "a.test";
$dest = "b.test";

if (file_exists($dest)) {

    unlink($dest); // So we don't append to an existing file
}

$fp = fopen($src,'rb');

if ($fp) {

    while(!feof($fp)){

        $buffer = base64_encode(fread($fp,1024));
        write($dest,$buffer);
    } 

    fclose($fp);
}

function write($file,$buffer) { 
    
    $fp = fopen($file,'ab');

    fwrite($fp,base64_decode($buffer));
    fclose($fp);    
}   

echo md5_file($src)."\n";  // 88e4af2f85080a280e7f00e50d96b7f7
echo md5_file($dest)."\n"; // 88e4af2f85080a280e7f00e50d96b7f7

至于如何通过 HTTP 流式传输文件,您可能需要查看: