Генерація унікальних імен для завантаження

Дмитро Єлісєєв »Блог» Програмування »Генерація унікального імені файлу в PHP проектах

Генерація унікальних імен для завантаження

C найперших проектів, що підтримують завантаження файлів на сервер, будь-який програміст стикається з необхідністю створення унікальних випадкових імен для завантажених файлів. Розглянемо кілька варіантів вирішення даної проблеми.

Припустимо, ми повинні зберігати всі файли в одну папку. Щоб файли не повторювалися і щоб не виникало проблем з кирилицею нам краще давати їм унікальні імена виду

Найлегший варіант - це використання вбудованої в PHP функції uniqid ():

Ця функція поверне випадкову 13-символьний рядок. Якщо ж потрібно робити імена довше, то можна використовувати функції обчислення хеша від випадкової рядки:

Функція md5 () генерує 32-символьний рядок. Можна, звичайно використовувати будь-яку іншу функцію. При бажанні можна встановити будь-яку довжину від 1 до 32 обрізавши md5-хеш функцією substr ():

Якщо потрібно зберігати файл з розширенням, то його розширення можна легко приписувати до ідентифікатора:

Це прості способи, але у них є один недолік: унікальність імені не контролюється, а отже зможе призвести до перезапису старого файлу при випадковій генерації такого ж імені для нового файлу. І ця ймовірність тим вище, чим більше файлів збережено.

Щоб уникнути перезапису нам необхідно перевіряти папку на відсутність такого ж файлу. Напишемо функцію, що повернений від цього недоліку:

Тут в постусловіем циклу здійснюється перевірка на наявність файлу. Якщо файл з таким ім'ям вже є, то генерується наступне ім'я. Замість md5 (microtime (). Rand (0, 9999)) для генерації ідентифікатора можна використовувати будь-який варіант з розібраних вище.

Розглянемо приклад завантаження зображення за допомогою цієї функції:

В Yii для отримання розширення зручно користуватися об'єктом $ file класу CUploadedFile:

За допомогою функції DFileHelper :: getRandomFileName () ми генеруємо унікальне ім'я файлу для папки upload / images і використовуємо це ім'я для завантаження. Тепер файли ніколи не перезапишуть, так як імена ніколи не співпадуть.

Як багатьом відомо, для зберігання налаштувань програми в Yii виділений спеціальний розділ `params` в файлі конфігурації. Це рішення досить просте, але воно не дозволяє легко змінювати налаштування самому користувачеві в панелі управління сайту. Черговий питання російською форумі Yii наштовхнув мене поділитися своїм варіантом вирішення згаданого там питання.

Досить часто виникає необхідність простежити час виконання деяких фрагментів програмного коду і відстежити особливо повільні ділянки для їх подальшої оптимізації. Наявні налагоджувальні розширення не проникають всередину ваших файлів, а частіше виводять тільки загальний час виконання скрипта. Для локального рефакторінга і оптимізації вони не підходять.

З інтересом Новомосковськ всі ваші статті, але відносного правильності способу створення унікального імені файлу, який викладено в цьому матеріалі, виникають сумніви.
Все, що робить статичний метод DFileHelper :: getRandomFileName () - це генерує унікальне (на момент генерації) ім'я файлу в рамках заданої директорії.
Однак, уявімо, що з додатком паралельно працюють кілька клієнтів (кліент1 і кліент2):
Кліент1 викликає метод getRandomFileName () - генерується унікальне ім'я;
Кліент2 викликає цей же метод з деяким запізненням, але ще до виклику Кліентом1 методу, який запише файл в директорію.

У цій ситуації може статися таке, що і для Кліента1, і для Кліента2 буде створено одне і теж "унікальне" ім'я, але Кліент2 не впізнає про це, оскільки Кліент1 ще не справив запис файлу в каталог, а адже лише після цього метод file_exists ( ) зможе визначити, що файл з таким ім'ям вже існує в директорії.

Вважаю, що після створення унікального імені необхідно відразу ж записувати файл в директорію (порожній) і після цього повертати, дійсно унікальне ім'я клієнта.

Сейчаc від цього рятує тільки rand (0, 9999) в імені, що дає вкрай малу верятность цієї події:

Можна підвищити верхню межу до мільйона, що знизить можливість збігу до однієї мільйонної.

Але все одно створення порожнього файлу не врятує, так як це «відразу ж» теж не буде миттєвим.