【问题标题】:PHP - Chunked file copy (via FTP) has missing bytes?PHP - 分块文件副本(通过 FTP)缺少字节?
【发布时间】:2012-07-02 16:15:30
【问题描述】:

所以,我正在编写一个分块文件传输脚本,旨在将文件(无论大小)复制到远程服务器。它几乎工作得非常好(我测试了一个 26 字节的文件,哈哈)但是当我开始做更大的文件时,我注意到它不太工作。例如,我上传了一个 96,489,231 字节的文件,但最终的文件是 95,504,152 字节。我用一个 928,670,754 字节的文件测试它,复制的文件只有 927,902,792 字节。

有没有其他人经历过这种情况?我猜feof() 可能正在做一些奇怪的事情,但我不知道如何替换它或测试它。为了您的方便,我评论了代码。 :)

<?php

// FTP credentials
$server = CENSORED;
$username = CENSORED;
$password = CENSORED;

// Destination file (where the copied file should go)
$destination = "ftp://$username:$password@$server/ftp/final.mp4";

// The file on my server that we're copying (in chunks) to $destination.
$read = 'grr.mp4';

// If the file we're trying to copy exists...
if (file_exists($read))
{
    // Set a chunk size
    $chunk_size = 4194304;

    // For reading through the file we want to copy to the FTP server.
    $read_handle = fopen($read, 'rb');

    // For appending to the destination file.
    $destination_handle = fopen($destination, 'ab');

    echo '<span style="font-size:20px;">';
    echo 'Uploading.....';

    // Loop through $read until we reach the end of the file.
    while (!feof($read_handle))
    {
        // So Rackspace doesn't think nothing's happening.
        echo PHP_EOL;
        flush();

        // Read a chunk of the file we're copying.
        $chunk = fread($read_handle, $chunk_size);

        // Write the chunk to the destination file.
        fwrite($destination_handle, $chunk);

        sleep(1);
    }
    echo 'Done!';
    echo '</span>';
}

fclose($read_handle);
fclose($destination_handle);
?>

编辑

我(可能已经)确认脚本最终以某种方式死亡,并且没有损坏文件。我创建了一个简单的文件,每行对应于行号,最多 10000,然后运行我的脚本。它在第 6253 行停止。但是,脚本仍然返回“完成!”最后,所以我无法想象这是一个超时问题。奇怪!

编辑 2

我已确认问题存在于fwrite() 的某处。通过在循环内回显$chunk,完整的文件将被正确返回。但是写入的文件还是不匹配。

编辑 3

如果我在 fwrite() 之后立即添加 sleep(1),它似乎可以工作。然而,这使得脚本需要一百万年才能运行。会不会是 PHP 的 append 有一些固有的缺陷?

编辑 4

好吧,不知何故,进一步将问题隔离为 FTP 问题。当我在本地运行此文件副本时,它工作正常。但是,当我使用文件传输协议(第 9 行)时,字节丢失了。尽管fopen() 的两种情况都有二进制标志,但仍会发生这种情况。这可能是什么原因造成的?

编辑 5

我找到了解决办法。修改后的代码在上面——我会尽快自己发布答案。

【问题讨论】:

  • 如果你打开一个二进制文件你应该使用 fopen(...,'rb')
  • fopen(..., 'r') 替换为fopen(..., 'rb') 具有相同的效果。不过谢谢!
  • 也许也可以试试 $destination_handle = fopen($destination, 'ab');
  • 在将其发送到远程服务器之前是否会出现问题?
  • 我实际上并不确定我将如何测试它。这似乎只发生在非常大的文件(例如视频,如上面的代码中),所以我真的不知道如何找到丢失的数据。

标签: php ftp eof chunked


【解决方案1】:

我找到了一个修复方法,但我不确定它的确切原因。只需在写入每个块后睡觉即可解决问题。我将块大小提高了很多以加快速度。虽然这可以说是一个糟糕的解决方案,但它应该适用于我的用途。无论如何,谢谢,伙计们!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-19
    • 1970-01-01
    • 2012-01-12
    • 2010-10-30
    • 1970-01-01
    相关资源
    最近更新 更多