そのため、私はファイル (大小を問わず) をリモート サーバーにコピーするためのチャンク ファイル転送スクリプトを作成しています。それはほとんど素晴らしく動作します (そして、私がテストした 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
修正を見つけました。変更されたコードは上記のとおりです。できるだけ早く、自分で回答を投稿します。