Когда пользователь загружает файл, он случайно заменяется загрузкой другого пользователя, я, наконец, отслеживал проблему с PHP и имя файла tmp, которое повторно используется. Есть ли способ исправить это? Есть ли способ сделать лучшие случайные имена? Кажется, он со временем ухудшается, так как в случайном имени файла семя становится слабее? Это на PHP 5.2.8 и FreeBSD 7.0
Вот журнал, показывающий, как используется одно и то же имя файла tmp и перезаписывается другой загрузкой: http://pastebin.com/m65790440
Любая помощь ВОЗМОЖНО высоко ценится. Я пытаюсь исправить это более 4 месяцев и со временем ухудшился. Спасибо.
EDIT: Имейте в виду, что это не проблема с PHP-кодом, это происходит до того, как он достигнет любого PHP-кода, файл, полученный через $ _FILES ['name'] ['tmp_name'], некорректен, когда он получен и его прослеживается что он перезаписывается чужой загрузкой, прежде чем он достигнет сценария обработки загрузки
Похоже, что что-то серьезно не так с вашей установкой PHP или любым системным вызовом, который PHP внутренне использует для генерации случайных имен файлов (скорее всего, tempnam ).
Для всех остальных: PHP обрабатывает загруженные файлы внутри, прежде чем код пользователя будет обработан. Эти имена хранятся в $_FILES['file']['tmp_name']
(где «файл» – это (цитированное) имя элемента ввода файла в форме).
После преследования соответствующего кода до _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 (как и выше) для фактического создания произвольного имени файла. manpage для mkstemp упоминает в разделе BUGS, что arc4random()
не является реентерабельной. Возможно, что два одновременных запроса входят в секцию критического кода и возвращают одно и то же имя tmp_name
– я слишком мало знаю о том, как Apache работает с mod_php или php-cgi, чтобы прокомментировать там (хотя использование FastCGI / php-cgi может работать – я не могу успешно прокомментировать это в настоящее время).
Однако, стремясь к самому простому решению, если вы не совсем испытываете tmp_name
имя файла tmp_name
, но вместо этого сталкиваетесь с другими загруженными файлами (например, если вы используете часть имени файла tmp_name как единственный источник уникальности в сохраненном имени файла) , вы можете столкнуться с столкновениями из-за парадокса рождения . В другом вопросе вы упоминаете, что у вас есть около 5 000 000 файлов, и в еще одном вопросе вы упомянули о том, что 30-40 килобайт загружает день. Это поражает меня как отличную ситуацию для столкновения парадоксального дня рождения. В man-странице mktemp упоминается, что (если использовать шесть «Xs», как это делает PHP) есть 56 800 235 584 возможных имени файла (62 ** 6 или 62 ** n, где n = число «Xs» и т. Д.). Однако, учитывая, что у вас есть более 5 миллионов файлов, вероятность столкновения составляет примерно 100% (другая эвристика предполагает, что вы уже испытали некоторый порядок из 220 столкновений, если ((файлы * (файлы-1)) / 2) / (62 ** 6) означает все, где файлы = 5 000 000). Если это проблема, с которой вы столкнулись (возможно, если не добавить дополнительную энтропию к сгенерированному загруженному имени файла), вы можете попробовать что-то вроде move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.'))
– идея состоит в том, чтобы добавить больше случайности к случайному имени файла, предотвращая столкновения. Альтернативой может быть добавление еще двух «Xs» к строке 134 main/php_open_temporary_file.c
и перекомпиляции.
PHP работает под apache, как mod_php
?
Вы можете попытаться создать временный каталог загрузки для каждого процесса , имя которого содержит ваш php getmypid()
, а затем ini_set
ваш процесс PHP ' upload_tmp_dir
в этот каталог. Это не будет работать, если для каждого запроса создается новый php
процесс.
Переместите ваши файлы в каталог пользователя после их загрузки. Эти временные файлы должны быть удалены.
Я бы рекомендовал использовать генератор GUID для имени файла, увидев, что вы получаете так много.