Итак, я пишу фрагментированный сценарий передачи файлов, предназначенный для копирования файлов — маленьких и больших — на удаленный сервер. Это работает почти фантастически (и с 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
Кажется, это сработает, если я добавлю sleep(1) сразу после fwrite(). Однако из-за этого сценарий выполняется миллион лет. Возможно ли, что добавление PHP имеет какой-то врожденный недостаток?
РЕДАКТИРОВАТЬ 4
Хорошо, каким-то образом еще больше изолировал проблему от проблемы с FTP. Когда я запускаю эту копию файла локально, она работает нормально. Однако, когда я использую протокол передачи файлов (строка 9), байты отсутствуют. Это происходит, несмотря на то, что двоичный файл помечает два случая fopen()
. Что может быть причиной этого?
РЕДАКТИРОВАТЬ 5
Я нашел исправление. Модифицированный код приведен выше - я опубликую ответ самостоятельно, как только смогу.
fopen(..., 'r')
наfopen(..., 'rb')
дала тот же эффект. Спасибо хоть! - person Nathanael   schedule 02.07.2012fwrite()
. При повторении$chunk
внутри цикла полный файл возвращается в обязательном порядке. Однако записанный файл все равно усекается. - person Nathanael   schedule 02.07.2012