У меня есть игра, которую я пытаюсь выпустить, и ее размер составляет 7 ГБ. Я использую PHP для его распространения. Написанный мной сценарий PHP может начать загрузку без проблем, и я могу использовать тот же сценарий для гораздо меньшего размера zip-архива, и он отлично загружается. Я также могу без проблем распаковать файл меньшего размера и извлечь его содержимое. Однако, когда я пытаюсь загрузить файл большего размера, кажется, что он прерывается раньше, где-то между 3 ГБ и 4,5 ГБ. Это в основном случайное, хотя большую часть времени оно имеет тенденцию останавливаться на отметке 4,3 ГБ. Очевидно, что когда я пытаюсь распаковать неполный файл, он поврежден и не может быть разархивирован. также пробовал использовать while (!feof($handle))
вместо while($size > $bytes_read)
с тем же результатом. Я также пробовал отключить сжатие через .htaccess, например, SetEnv no-gzip dont-vary
. Моя версия php - 7.3
.
Я застрял на этом несколько дней и не уверен, что делаю не так. Помощь будет принята с благодарностью!
РЕДАКТИРОВАТЬ с дополнительной информацией:
- Настройка
ini_set('memory_limit',-1);
, похоже, не повлияла. - Как test, я установил
usleep(1000000);
, загрузка стала намного медленнее, и файл перестал загружаться примерно на 900 МБ. Это заставляет меня думать, что это должна быть проблема с тайм-аутом, но тогда почему ini_set('max_execution_time','0');
не решает это? var_dump(ini_get('safe_mode'));
равно bool(false)
- Я считаю, что тайм-аут время ожидания Apachi. Я рассчитал время загрузки несколько раз, и она останавливается ровно через 300 секунд, что является тайм-аутом Apachi по умолчанию. У меня есть бизнес-аккаунт в GoDaddy, и они отказываются изменять тайм-аут Apachi.
ob_clean(); // Clear any previously written headers in the output buffer
flush();
ini_set('memory_limit','1G');
ini_set('max_execution_time','0');
$file = "builds/RoA.zip";
$chunksize = 5 * (1024 * 1024); // different chunk sizes don't make a difference
ob_start();
set_time_limit(0);
// ini_get(max_execution_time) returns 0
if (is_file($file))
{
$ext = pathinfo($file, PATHINFO_EXTENSION);
$basename = pathinfo($file, PATHINFO_BASENAME);
$size = intval(sprintf("%u", filesize($file)));
// http headers for zip downloads
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: public");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0", FALSE);
header("Content-Description: File Transfer");
//header("Content-Type: application/zip");
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$size); // gives correct size to Google Chrome. Is able to see progress.
header("Content-Disposition: attachment; filename=\"".$basename."\"");
$handle = fopen($file, 'rb') or die("Couldn't get handle");
$bytes_read = 0;
while($size > $bytes_read)
{
set_time_limit(30);
$buffer = fread($handle, $chunksize);
echo $buffer;
$bytes_read+=$chunksize;
ob_flush();
flush();
}
fclose($handle);
ob_end_flush();
exit;
}