Создание основанного на времени уникального имени файла для загрузки без создания условия гонки - PullRequest
5 голосов
/ 11 августа 2009

Я генерирую уникальное имя файла для загруженных файлов со следующим кодом

$date = date( 'U' );
$user = $_SERVER[REMOTE_ADDR];
$filename = md5($date.$user);

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

Например, я использую скрипт загрузки / изменения размера / сохранения изображения. Первой операцией скрипта является копирование и сохранение изображения с измененным размером, которому я использую функцию даты, чтобы назначить уникальное имя. Затем скрипт обрабатывает сохранение и сохраняет всю загрузку и присваивает ему имя. В конце скрипта ($thumb и $full - переменные) мне нужно вставить в базу данных MySQL имена файлов, которые я использовал при сохранении закачек.

Проблема в том, что иногда на больших изображениях это занимает больше секунды (или во время процесса, смена секунд), в результате чего в базу данных помещается другое имя файла, а не то, под которым файл действительно сохраняется.

Разве это не хорошая идея использовать этот метод именования?

Ответы [ 6 ]

5 голосов
/ 11 августа 2009

AFAIK, это отличный способ назвать файлы, хотя я бы проверил file_exists() и, возможно, добавил бы случайное число.

Вам нужно сохранить это имя файла в переменной и снова обратиться к нему позже, вместо того, чтобы каждый раз полагаться на алгоритм. Это может быть сохранено пользователем $_SESSION, файлом cookie, переменной GET и т. Д. Между загрузками страниц.

Надеюсь, что поможет

2 голосов
/ 11 августа 2009

Просто хочу добавить, что в php есть функция для создания идентификаторов: uniqid. Вы также можете поставить перед идентификатором строку (возможно, дату?).

Всегда проверяйте ввод вашего пользователя и заголовки сервера!

2 голосов
/ 11 августа 2009

Я бы рекомендовал хранить имя файла в сеансе (согласно AI). Если вы сохраните его в одной из других переменных, конечный пользователь с большей вероятностью сможет атаковать систему через него. MD5 пользователя, объединенного с rand (), был бы хорошим способом получить длинный список уникальных значений. Использование rand () может привести к более высокому проценту конфликтов.

Я не уверен в том, какой процесс вы используете для загрузки файлов, но другой способ обработки загрузки файлов - это встроенные в PHP обработчики. Вы можете загрузить файл, а затем использовать «безопасные» методы для извлечения загруженных файлов из временного пространства. (временное пространство в этом случае может быть безопасно расположено вне директивы dir с открытым основанием, чтобы предотвратить вмешательство). is_uploaded_file () и move_uploaded_file () from: http://php.net/manual/en/features.file-upload.post-method.php пример 2 может решить проблему, с которой вы столкнулись.

Определенно проверьте наличие файла в этом месте, если вы выбираете имя файла на лету. Если пользовательский ввод разрешен каким-либо образом в форме или форме, проверьте и отфильтруйте аргумент, чтобы убедиться, что он безопасен. Кроме того, если папка хранения доступна через Интернет, убедитесь, что вы изменили имя и, возможно, расширение. Вы не хотите, чтобы кто-то мог загружать код и затем выполнять его. Это официально ведет к плохим действиям.

1 голос
/ 02 мая 2012

Я только что обнаружил, что в PHP есть встроенная функция для этого, называемая tempnam. Это даже избегает условий гонки. Смотри http://php.net/manual/en/function.tempnam.php.

0 голосов
/ 12 августа 2009

Не очень хорошая идея использовать ID, зависящий от времени - если вы загружаете два изображения одновременно, более позднее можно перезаписать ранее. Вы должны посмотреть на такую ​​функцию, как uniqid () . Однако, если этот скрипт загрузки / изменения размера / сохранения предназначен для «однопользовательского режима», то это не такая большая проблема.

К самой проблеме. Если бы я был тобой, я бы просто сохранил вычисленное имя файла в некоторой переменной и использовал переменную из этой точки. Вычисление уже вычислено - пустая трата времени. А при загрузке нескольких действительно больших изображений или нескольких изображений одновременно сценарий может занять даже 20 секунд. Вы не можете зависеть от того, что вы сделаете все, что хотите, за одну секунду.

0 голосов
/ 11 августа 2009

Почему бы не использовать

$filename = md5(rand());

Это будет в значительной степени уникально в каждом случае. И если вы обнаружите, что $filename уже существует, вы можете просто позвонить еще раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...