Имена временных файлов PHP для загрузки файлов - PullRequest
8 голосов
/ 10 марта 2009

Когда пользователь загружает файл, случайным образом он заменяется загрузкой другого пользователя, я наконец-то отследил проблему в PHP и повторно использовал имя файла tmp. Есть ли способ это исправить? Есть ли способ сделать лучшие случайные имена? Кажется, со временем ухудшается, так как в случайном имени файла начальное число становится слабее? Это на PHP 5.2.8 и FreeBSD 7.0

Вот журнал, показывающий, как то же имя файла tmp используется и перезаписывается при другой загрузке: http://pastebin.com/m65790440

Любая помощь приветствуется. Я пытался исправить это более 4 месяцев и со временем стало хуже. Спасибо.

РЕДАКТИРОВАТЬ: имейте в виду, что это не проблема кода PHP, это происходит до того, как он достигает какого-либо кода PHP, файл, полученный через $ _FILES ['name'] ['tmp_name'], неверен, когда он получен его проследили, что он перезаписывается с чужой загрузкой до того, как он достигнет сценария обработки загрузки

Ответы [ 5 ]

4 голосов
/ 10 марта 2009

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

Для всех остальных: PHP обрабатывает загруженные файлы внутри до того, как пользовательский код когда-либо обрабатывается. Эти имена хранятся в $_FILES['file']['tmp_name'] (где 'file' - это (в кавычках) имя элемента ввода файла в форме).

3 голосов
/ 19 июля 2010

После погони за соответствующим кодом до _gettemp в реализации libc во FreeBSD 7, я не могу понять, как содержимое файла tmp_name может быть недопустимым. (Чтобы отследить это, вы можете скачать копию PHP 5.2.8 и прочитать в main/rfc1867.c - строка 1018 вызывает в main/php_open_temporary_file.c функцию, начинающуюся со строки 227, которая выполняет основную работу в функции, начинающейся со строки 97, который, однако, по сути является просто оболочкой для mkstemp в вашей системе, который можно найти в реализации libc * FreeBSD в строке 66 (связанный), в которой используется _gettemp (то же, что и выше) на самом деле генерировать случайное имя файла. Однако на странице man для mkstemp в разделе BUGS упоминается, что arc4random() функция не является реентерабельной. Это может что 2 одновременных запроса входят в критическую секцию кода и возвращают один и тот же tmp_name - я слишком мало знаю о том, как Apache работает с mod_php или php-cgi, чтобы комментировать там (хотя использование FastCGI / php-cgi может работать - я могу ' в настоящее время это успешно комментируется).

Однако, стремясь к простейшему решению, если вы не совсем чувствуете, что файл tmp_name является недействительным, но вместо этого сталкиваются с другими загруженными файлами (например, если использовать часть имени файла tmp_name в качестве единственного источника уникальности) в сохраненном имени файла) вы можете столкнуться с коллизиями из-за дня рождения парадокса . В другом вопросе вы упоминаете о необходимости перемещения около 5 000 000 файлов, а в еще одном вопросе вы упоминаете о получении 30-40 тыс. Загрузок в день. Это кажется мне главной ситуацией для столкновения с парадоксом дня рождения. В справочной странице mktemp упоминается, что (если используется шесть «X», как в PHP), существует 56 800 235 584 возможных имен файлов (62 ** 6 или 62 ** n, где n = количество «X» и т. Д.) , Однако, учитывая, что у вас более 5 миллионов файлов, вероятность коллизии составляет приблизительно 100% (другая эвристика предполагает, что вы уже испытали порядка 220 коллизий, если ((файлы * (files-1)) / 2) / (62 ** 6) означает что угодно, где files = 5 000 000). Если с этой проблемой вы столкнулись (вероятно, , если не добавляет дополнительной энтропии к сгенерированному загруженному имени файла), вы можете попробовать что-то вроде move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.')) - идея состоит в том, чтобы добавить больше случайности к случайному имени файла, предотвращение столкновений. Альтернативой может быть добавление еще двух 'X' к строке 134 main/php_open_temporary_file.c и перекомпиляция.

2 голосов
/ 10 марта 2009

PHP работает под Apache, как mod_php?

Вы можете попробовать создать временный каталог загрузки для каждого процесса , имя которого содержит ваш php getmypid(), затем ini_set ваш процесс PHP 'upload_tmp_dir в этот каталог. Это не будет работать, если для каждого запроса будет создан новый процесс php.

0 голосов
/ 10 марта 2009

Переместите ваши файлы в каталог пользователя после того, как они были загружены. Эти временные файлы должны быть удалены.

0 голосов
/ 10 марта 2009

Я бы порекомендовал использовать генератор GUID для имени файла, видя, что вы получаете так много.

...