2

そのため、私はファイル (大小を問わず) をリモート サーバーにコピーするためのチャンク ファイル転送スクリプトを作成しています。それはほとんど素晴らしく動作します (そして、私がテストした 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) を追加するとうまくいくようです。ただし、スクリプトの実行には 100 万年かかります。PHPの追加に固有の欠陥がある可能性はありますか?

編集4

よし、どういうわけか、問題を FTP の問題にさらに切り分けました。このファイル コピーをローカルで実行すると、正常に動作します。ただし、ファイル転送プロトコル (9 行目) を使用すると、バイトが失われます。これは、 の 2 つのケースのバイナリ フラグにもかかわらず発生していfopen()ます。これを引き起こしている可能性があるのは何ですか?

編集5

修正を見つけました。変更されたコードは上記のとおりです。できるだけ早く、自分で回答を投稿します。

4

1 に答える 1

1

なぜそれが機能するのか正確にはわかりませんが、修正を見つけました。各チャンクを書き込んだ後にスリープするだけで問題が解決します。処理を高速化するために、チャンク サイズをかなり大きくしました。これは間違いなく悪い解決策ですが、私の用途ではうまくいくはずです。とにかくありがとう、みんな!

于 2012-07-03T17:28:14.553 に答える