За последние 24 часа нас посетили 17157 программистов и 1651 робот. Сейчас ищут 935 программистов ...

Чистка не системных временных файлов

Тема в разделе "Прочие вопросы по PHP", создана пользователем Старый Пень, 11 сен 2014.

  1. Старый Пень

    Старый Пень Новичок

    С нами с:
    11 сен 2014
    Сообщения:
    6
    Симпатии:
    0
    Здравствуйте, уважаемые господа коллеги. :)

    В общем я пришел сюда за идеей. У меня есть задача, которая для меня сейчас очень насущна, но решить я её не могу. С самим программированием у меня все нормально, но вот не хватает фантазии.

    Задача следующая. Гружу огромные (по нескольку ГБ) файлы через ajax+php, естественно, по частям, но не в этом суть. Файлы грузятся нормально и все счастливы и алгоритм следующий. Приходит часть файла, php её принимает и сохраняет во временной папке (папка лежит на уровень выше корня домена), когда приходит следующий фрагмент, php побайтно склеивает её с первой и так далее, а временный файл растет. По приклейке последнего файла php переносит файл в папку хранения. А вот теперь кульминация. Бывает такое, что пользователи не догружают файлы, связь обрывается у него или еще чего. Как оказалось, такое происходит достаточно часто и эти недогруженные временные файлы остаются во временной папке и просто занимают место, что не очень хорошо, вы же понимаете. В общем мне нужна идея как очищать эти файлы и случайно не удалить файлы, которые загружаются в данный момент.
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Не грузи по-частям - всё будет само чиститься.
     
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    Код (PHP):
    1. if (filemtime($tempFilename) < time() - MY_TIMEOUT) {
    2.   unlink($tempFilename);
    3. } 
    Делать это можно как по крону, так и в любом часто вызываемом скрипте.
     
  4. Старый Пень

    Старый Пень Новичок

    С нами с:
    11 сен 2014
    Сообщения:
    6
    Симпатии:
    0
    Не по частям не пойдет. Грузятся файлы размером в несколько гигабайт, а делать максимальную длину post запроса в терабайт (потому что я не знаю в итоге какой будет самый большой файл) не очень хорошо. Тем более скрипт в последствии может быть использован не только на этом сервере, но и на серверах, где может не быть возможности настроить эти параметры у PHP и Apache. Поэтому нужно грузить частями. Размер каждой части настраивается админом. Если нет возможности изменить настройки в PHP, то выставляешь деление по 2мб и грузится, теоретически, бесконечно большой файл, т.к. ограничение не нарушено. Еще ajax загрузка - обязательное требование и если не делить файл, то PHP начинает забивать оперативу и, если стоит настройка выделенной памяти по умолчанию (128мб), то при загрузке, примерно, метрах на 60-80, скрипт вываливает ошибку что память переполняется и сбрасывается (это при 1 активном пользователе, а их может быть много). filemtime рассматривал, но вот какая может быть фигня. Где-то админ установит "делить по 50 мб" а у клиента слабый интернет, то эти 50 мб могут грузится 30 минут, за которые скрипт уже удалит первую часть файла. Если поставить, к примеру, проверку аж на сутки, то tmp не хило так может забиться. А что если я вместо своей папки tmp буду использовать системную, то мне это поможет?
     
  5. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Что-то ты там намудрил...
     
  6. Старый Пень

    Старый Пень Новичок

    С нами с:
    11 сен 2014
    Сообщения:
    6
    Симпатии:
    0
    Ну так это понятно, но что посоветуйте-то?
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    Старый Пень, а что не так? Я вам посоветовал удалять старые файлы, проверяя их дату изменения.

    Допустим устанавливаете величину MY_TIMEOUT равную 24часам. Если файл во временной папке старше суток, то видимо он уже нерабочий. Проще не бывает!
     
  8. Старый Пень

    Старый Пень Новичок

    С нами с:
    11 сен 2014
    Сообщения:
    6
    Симпатии:
    0
    Да, я это принял, но вот какая может быть фигня. Где-то админ установит "делить по 50 мб" а у клиента слабый интернет, то эти 50 мб могут грузится 30 минут, за которые скрипт уже удалит первую часть файла. Если поставить, к примеру, проверку аж на сутки, то tmp не хило так может забиться. А то и вообще диск забить.
     
  9. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.131
    Симпатии:
    1.250
    Адрес:
    там-сям
    Ну поставьте 3 часа, 1 час или сколько сколько Вам покажется нужным.
    Какого еще рецепта Вы ждете? Супер-интеллектуальный алгоритм, определяющий, что пользователю не надоело?

    Добавлено спустя 2 минуты 39 секунд:
    IMHO, введение квот для пользователей вам бы очень помогло, но это сильно другая задача.
     
  10. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    А как реализована загрузка по-частям, и почему пхп жрет память?
     
  11. Старый Пень

    Старый Пень Новичок

    С нами с:
    11 сен 2014
    Сообщения:
    6
    Симпатии:
    0
    PHP
    Код (Text):
    1. if (!isset($_SESSION['tmp_file_name']))
    2.                     {
    3.                         $_SESSION['tmp_file_name'] = md5(time().$path.$file_name).'_';
    4.                     }
    5.                     $tmp_number = count(glob('../tmp/'.$_SESSION['tmp_file_name'].'*'))+1;
    6.                     if (!$putdata = fopen("php://input", "rb")) { echo 'Поток данных не регистрируется'; exit; };
    7.                     if (!$fp = fopen('../tmp/'.$_SESSION['tmp_file_name'].$tmp_number, "w")) { echo 'Путь TMP не доступен'; exit; };
    8.                     while ($data = fread($putdata, 4096))
    9.                     {
    10.                         if (!fwrite($fp, $data)) { echo 'Недостаточно прав для записи'; exit; };
    11.                     }
    12.                     fclose($fp);
    13.  
    14.                     if ($_REQUEST['part'] == '0')
    15.                     {
    16.                         fclose($putdata);
    17.                         $part_count = count(glob('../tmp/'.$_SESSION['tmp_file_name'].'*'));
    18.                         if ($part_count > 1)
    19.                         {
    20.                             if (!$fp = fopen($path.$file_name, "w")) { echo 'Путь для записи не доступен'; exit; };
    21.                             for ($i=1; $i<=$part_count; $i++)
    22.                             {
    23.                                 $tmp_file_name = '../tmp/'.$_SESSION['tmp_file_name'].$i;
    24.                                 $tmp_file = fopen($tmp_file_name, "rb");
    25.                                 fwrite($fp, fread($tmp_file, filesize($tmp_file_name)));
    26.                                 unlink('../tmp/'.$_SESSION['tmp_file_name'].$i);
    27.                             }
    28.                             fclose($fp);
    29.                         } else
    30.                         {
    31.                             exec('mv ../tmp/'.$_SESSION['tmp_file_name'].'1 '.$path.$file_name);
    32.                             unlink('../tmp/'.$_SESSION['tmp_file_name'].'1');
    33.                         }
    34.                         touch($path.$file_name, $file_time);
    35.                         unlink($_SESSION['tmp_file_name']);
    36.                         if ($file_type == '.jpg' || $file_type == '.png' || $file_type == '.jpeg') oneFile::setWaterMark($path.$file_name, $file_type);
    37.                     }
    JS

    Код (Text):
    1. function PartLoad(log_id, name, type, hidd, file, reload, byte_from)
    2. {
    3.     byte_from = byte_from || 0;
    4.     var load = file.slice(byte_from, byte_from+<?php echo $configs[5]; ?>);
    5.     var xhr1 = new XMLHttpRequest();
    6.     //onProgress(byte_from, file.size, log_id);
    7.     xhr1.upload.onprogress = function(event) {
    8.         onProgress(byte_from+event.loaded, file.size, log_id);
    9.     };
    10.     xhr1.onload = xhr1.onload = function() {
    11.         if(this.status != 200 || this.responseText != 'OK') {
    12.             onError(log_id, this.responseText);
    13.             return true;
    14.         } else
    15.         {
    16.             if ((file.size - byte_from) <= <?php echo $configs[5]; ?>)
    17.             {
    18.                 onProgress(file.size, file.size, log_id);
    19.                 onSuccess(log_id, type);
    20.                 return true;
    21.             } else
    22.             {
    23.                 PartLoad(log_id, name, type, hidd, file, reload, byte_from+<?php echo $configs[5]; ?>);
    24.             }
    25.         }
    26.     };
    27.     var query = '';
    28.     if ((file.size - byte_from) <= <?php echo $configs[5]; ?>)
    29.     {
    30.         query = "name="+name+"&type="+type+"&hidd="+hidd+"&total="+file.size+"&check="+reload+"&part=0";
    31.     } else {
    32.         query = "name="+name+"&type="+type+"&hidd="+hidd+"&total="+file.size+"&check="+reload+"&part=1";
    33.     }
    34.     xhr1.open("POST", "oneFile.php?"+query, true);
    35.     xhr1.send(load);
    36. }
    37.  
    38. function upload(file, name, log_id, type, onSuccess, onProgress, file_type, hidd, reload) {
    39.     //Проверка фала
    40.     reload = reload || '0';
    41.     var xhr = new XMLHttpRequest();
    42.     xhr.onload = xhr.onerror = function()
    43.     {
    44.         if(this.status != 200 || this.responseText != 'OK') {
    45.             onError(log_id, this.responseText);
    46.         } else
    47.         {
    48.             PartLoad(log_id, name, type, hidd, file, reload);
    49.         }
    50.     };
    51.     xhr.open("GET", "oneFile.php?check="+file_type+"&total="+file.size, true);
    52.     xhr.send(null);
    53. }
     
  12. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    С интерфейсом работают сотрудники или клиенты?
     
  13. Старый Пень

    Старый Пень Новичок

    С нами с:
    11 сен 2014
    Сообщения:
    6
    Симпатии:
    0
    С интерфейсом работают и сотрудники и клиенты. Может быть даже такая ситуация, когда с ним будут работать все подряд.
     
  14. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Возьми сервак по-больше и вопрос решен.