Файл PHP fwrite () приводит к внутренней ошибке сервера

Я хочу загрузить большие файлы на мой сервер. Я склеиваю эти файлы перед загрузкой в ​​макс. 1 МБ кусков. Если один чанк загружен, этот чанк добавляется в файл.
На моем локальном сервере все работает хорошо, но если я тестирую этот скрипт на своем веб-сервере (размещенном в Strato -.-), процесс завершается с Внутренней ошибкой сервера каждый раз, когда размер добавляемого файла на сервере увеличивается до 64 МБ.
Я думаю, что это (конечно?) Вызвано ограничением Strato. Может быть, что-то с памятью, но я не могу объяснить себе, почему это происходит.
Это скрипт (версия PHP 5.6):

$file = $_FILES['chunk'];
$server_chunk = fopen($uploadDir.$_POST['file_id'], "ab");
$new_chunk = fopen($file['tmp_name'], "rb");

while(!feof($new_chunk)) //while-loop is optional
{
fwrite($server_chunk, fread($new_chunk, 1024));
};
fclose($new_chunk);
fclose($server_chunk);

По моему мнению, в этом коде нет строки, где файл загружается в память, чтобы вызвать эту ошибку, или что-то другое может вызвать эту ошибку?

Я проверил журналы сервера, но нет никакой записи, если эта ошибка происходит.

php.ini

Я могу создать несколько 63MB файлов. Только если файлы превышают 64 МБ, сервер прерывает работу.

ОБНОВИТЬ:
Я написал следующий скрипт для объединения файловых блоков на сервере с cat.
Но я всегда получаю файл 8192B обратно.
Что-то не так с этим скриптом?
$ command — это что-то вроде:
/ bin / cat ../files/8_0 ../files/8_1 ../files/8_2 ../files/8_3

$command = '/bin/cat';
foreach($file_array AS $file_info)
{
$command = $command.' ../files/'.$file_info['file_id'].'_'.$file_info['server_chunkNumber'];
}
$handle1 = popen($command, "r");
$read = fread($handle1, $_GET['size']);
echo $read;

Я проверил результат. Байты в файле 8192B в точности совпадают с началом исходного файла. Так что, кажется, что-то работает …

Обновить:
я нашел этот.

Обновить:

$handle1 = popen($command, "r");
while(!feof($handle1))
{
$read = fread($handle1, 1024);
echo $read;
}

Это работает, я могу кусочно читать из ручки. Но, конечно, таким образом я сталкиваюсь с ограничениями по таймауту. Как я могу передать файл клиенту? Если на этот вопрос ответят все мои проблемы ушли;)

2

Решение

(см. обновление внизу)

Ошибка ограничения памяти выглядела бы иначе (но вы можете написать скрипт, который постоянно выделяет память, добавляя большие объекты в растущий массив, и смотрите, что происходит). Кроме того, ограничение памяти связано с ядром PHP, плюс сценарий, плюс структуры, плюс любой контент файла; даже если файл добавлен в должны были быть загружены или рассчитаны на ограничение памяти (может быть через mmap, даже если это кажется странным), в лучшем случае маловероятно, чтобы предел составлял 64 мегабайта.

Так это выглядит ограничение файловой системы на один размер файла мне. Есть несколько облачных файловых систем, которые имеют такие ограничения; но я не знаю ни одного такого на локальном дисковом хранилище. Я попросил бы подсказки к технической поддержке хостинга.

Некоторые попытки, которые я сделал бы:

  • двойная проверка $uploadDir если это не было назначено вами лично.

  • попробуйте создать файл по другому пути, чем $uploadDir, если конечно не в одной файловой системе

  • попробуйте проверить на наличие ошибок:

    if (!fwrite($server_chunk, fread($new_chunk, 1024))) {
    die("Error writing: ");
    }
    
  • параноидальная проверка на phpinfo (), чтобы убедиться, что нет странный странность, такая как переопределение функции. Вы можете расследовать по перечисляя функции и проверяя их (подделка, да, но вряд ли).

это действительно похоже на ограничение размера файла, не связанное с PHP. Ранее пользователи этого же хостинга сообщали о 32 Мб. Увидеть Вот а также Вот. Там люди не могут бежать mysqldump, или же tar резервное копирование. Это не имеет ничего общего с PHP напрямую.

Возможно, вы можете обойти эту проблему, сохранив файл порциями и загрузив его несколькими частями или передав Apache канал в cat программа, если есть.

Что произойдет, если вы сохраните файл 123.0001, файл 1230002, …, а затем, после загрузки, проверьте все фрагменты и отправьте соответствующий Content-Lengthсоздать командную строку для /bin/cat (если доступно …) и подключить поток к серверу. Вы все еще можете столкнуться с временными ограничениями, но это стоит того.

Пример:

<?php
$pattern    = "test/zot.*"; # BEWARE OF SHELL METACHARACTERS
$files      = glob($pattern);
natsort($files);
$size       = array_sum(array_map('filesize', $files));
ob_end_clean();
Header("Content-Disposition: attachment;filename=\"test.bin\";");
Header("Content-Type: application/octet-stream");
Header("Content-Length: {$size}");
passthru("/bin/cat {$pattern}");

Я проверил вышеупомянутое, и он загружает один файл размером 120 МБ из набора фрагментов по 10 МБ, упорядоченных как zot.1, zot.2, …, zot.10, zot.11, zot.12 (и да, я не использовал natsort вначале). Если мне удастся найти время, я запусту его снова на виртуальной машине с дросселированной сетью, так что сценарий будет иметь ограничение по времени 10 с, а загрузка займет 20 с. Это возможный этот PHP не прервет сценарий, пока passthru не вернется, поскольку я заметил, что хронометраж PHP не очень интуитивно понятен.

Следующий код выполняется с ограничением по времени три секунды. Он запускает команду, которая принимает четыре секунд, затем отправляет вывод в браузер, продолжает работать, пока его время не будет исчерпано.

<pre>
<?php
print "It is now " . date("H:i:s") . "\n";
passthru("sleep 4; echo 'Qapla!'");
print "It is now " . date("H:i:s") . "\n";
$x = 0;
for ($i = 0; $i < 5; $i++) {
$t = microtime(true);
while (microtime(true) < $t + 1.0) {
$x++;
}
echo "OK so far. It is now " . date("H:i:s") . "\n";
}

Результат:

It is now 20:52:56
Qapla!
It is now 20:53:00
OK so far. It is now 20:53:01
OK so far. It is now 20:53:02
OK so far. It is now 20:53:03( ! ) Fatal error: Maximum execution time of 3 seconds exceeded in /srv/www/rumenta/htdocs/test.php on line 9

Call Stack
#   Time    Memory  Function    Location
1   0.0002  235384  {main}( )   ../test.php:0
2   7.0191  236152  microtime ( )   ../test.php:9

Конечно, вполне возможно, что Strato использует более строгую проверку времени выполнения скрипта. Также у меня установлен PHP как модуль; возможно, для CGI, которые работают как независимые процессы, применяются другие правила.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]