Здравствуйте, уважаемые господа коллеги. В общем я пришел сюда за идеей. У меня есть задача, которая для меня сейчас очень насущна, но решить я её не могу. С самим программированием у меня все нормально, но вот не хватает фантазии. Задача следующая. Гружу огромные (по нескольку ГБ) файлы через ajax+php, естественно, по частям, но не в этом суть. Файлы грузятся нормально и все счастливы и алгоритм следующий. Приходит часть файла, php её принимает и сохраняет во временной папке (папка лежит на уровень выше корня домена), когда приходит следующий фрагмент, php побайтно склеивает её с первой и так далее, а временный файл растет. По приклейке последнего файла php переносит файл в папку хранения. А вот теперь кульминация. Бывает такое, что пользователи не догружают файлы, связь обрывается у него или еще чего. Как оказалось, такое происходит достаточно часто и эти недогруженные временные файлы остаются во временной папке и просто занимают место, что не очень хорошо, вы же понимаете. В общем мне нужна идея как очищать эти файлы и случайно не удалить файлы, которые загружаются в данный момент.
Код (PHP): if (filemtime($tempFilename) < time() - MY_TIMEOUT) { unlink($tempFilename); } Делать это можно как по крону, так и в любом часто вызываемом скрипте.
Не по частям не пойдет. Грузятся файлы размером в несколько гигабайт, а делать максимальную длину post запроса в терабайт (потому что я не знаю в итоге какой будет самый большой файл) не очень хорошо. Тем более скрипт в последствии может быть использован не только на этом сервере, но и на серверах, где может не быть возможности настроить эти параметры у PHP и Apache. Поэтому нужно грузить частями. Размер каждой части настраивается админом. Если нет возможности изменить настройки в PHP, то выставляешь деление по 2мб и грузится, теоретически, бесконечно большой файл, т.к. ограничение не нарушено. Еще ajax загрузка - обязательное требование и если не делить файл, то PHP начинает забивать оперативу и, если стоит настройка выделенной памяти по умолчанию (128мб), то при загрузке, примерно, метрах на 60-80, скрипт вываливает ошибку что память переполняется и сбрасывается (это при 1 активном пользователе, а их может быть много). filemtime рассматривал, но вот какая может быть фигня. Где-то админ установит "делить по 50 мб" а у клиента слабый интернет, то эти 50 мб могут грузится 30 минут, за которые скрипт уже удалит первую часть файла. Если поставить, к примеру, проверку аж на сутки, то tmp не хило так может забиться. А что если я вместо своей папки tmp буду использовать системную, то мне это поможет?
Старый Пень, а что не так? Я вам посоветовал удалять старые файлы, проверяя их дату изменения. Допустим устанавливаете величину MY_TIMEOUT равную 24часам. Если файл во временной папке старше суток, то видимо он уже нерабочий. Проще не бывает!
Да, я это принял, но вот какая может быть фигня. Где-то админ установит "делить по 50 мб" а у клиента слабый интернет, то эти 50 мб могут грузится 30 минут, за которые скрипт уже удалит первую часть файла. Если поставить, к примеру, проверку аж на сутки, то tmp не хило так может забиться. А то и вообще диск забить.
Ну поставьте 3 часа, 1 час или сколько сколько Вам покажется нужным. Какого еще рецепта Вы ждете? Супер-интеллектуальный алгоритм, определяющий, что пользователю не надоело? Добавлено спустя 2 минуты 39 секунд: IMHO, введение квот для пользователей вам бы очень помогло, но это сильно другая задача.
PHP Код (Text): if (!isset($_SESSION['tmp_file_name'])) { $_SESSION['tmp_file_name'] = md5(time().$path.$file_name).'_'; } $tmp_number = count(glob('../tmp/'.$_SESSION['tmp_file_name'].'*'))+1; if (!$putdata = fopen("php://input", "rb")) { echo 'Поток данных не регистрируется'; exit; }; if (!$fp = fopen('../tmp/'.$_SESSION['tmp_file_name'].$tmp_number, "w")) { echo 'Путь TMP не доступен'; exit; }; while ($data = fread($putdata, 4096)) { if (!fwrite($fp, $data)) { echo 'Недостаточно прав для записи'; exit; }; } fclose($fp); if ($_REQUEST['part'] == '0') { fclose($putdata); $part_count = count(glob('../tmp/'.$_SESSION['tmp_file_name'].'*')); if ($part_count > 1) { if (!$fp = fopen($path.$file_name, "w")) { echo 'Путь для записи не доступен'; exit; }; for ($i=1; $i<=$part_count; $i++) { $tmp_file_name = '../tmp/'.$_SESSION['tmp_file_name'].$i; $tmp_file = fopen($tmp_file_name, "rb"); fwrite($fp, fread($tmp_file, filesize($tmp_file_name))); unlink('../tmp/'.$_SESSION['tmp_file_name'].$i); } fclose($fp); } else { exec('mv ../tmp/'.$_SESSION['tmp_file_name'].'1 '.$path.$file_name); unlink('../tmp/'.$_SESSION['tmp_file_name'].'1'); } touch($path.$file_name, $file_time); unlink($_SESSION['tmp_file_name']); if ($file_type == '.jpg' || $file_type == '.png' || $file_type == '.jpeg') oneFile::setWaterMark($path.$file_name, $file_type); } JS Код (Text): function PartLoad(log_id, name, type, hidd, file, reload, byte_from) { byte_from = byte_from || 0; var load = file.slice(byte_from, byte_from+<?php echo $configs[5]; ?>); var xhr1 = new XMLHttpRequest(); //onProgress(byte_from, file.size, log_id); xhr1.upload.onprogress = function(event) { onProgress(byte_from+event.loaded, file.size, log_id); }; xhr1.onload = xhr1.onload = function() { if(this.status != 200 || this.responseText != 'OK') { onError(log_id, this.responseText); return true; } else { if ((file.size - byte_from) <= <?php echo $configs[5]; ?>) { onProgress(file.size, file.size, log_id); onSuccess(log_id, type); return true; } else { PartLoad(log_id, name, type, hidd, file, reload, byte_from+<?php echo $configs[5]; ?>); } } }; var query = ''; if ((file.size - byte_from) <= <?php echo $configs[5]; ?>) { query = "name="+name+"&type="+type+"&hidd="+hidd+"&total="+file.size+"&check="+reload+"&part=0"; } else { query = "name="+name+"&type="+type+"&hidd="+hidd+"&total="+file.size+"&check="+reload+"&part=1"; } xhr1.open("POST", "oneFile.php?"+query, true); xhr1.send(load); } function upload(file, name, log_id, type, onSuccess, onProgress, file_type, hidd, reload) { //Проверка фала reload = reload || '0'; var xhr = new XMLHttpRequest(); xhr.onload = xhr.onerror = function() { if(this.status != 200 || this.responseText != 'OK') { onError(log_id, this.responseText); } else { PartLoad(log_id, name, type, hidd, file, reload); } }; xhr.open("GET", "oneFile.php?check="+file_type+"&total="+file.size, true); xhr.send(null); }
С интерфейсом работают и сотрудники и клиенты. Может быть даже такая ситуация, когда с ним будут работать все подряд.