Я сделал скрипт загрузки на PHP. Как избежать перезаписи файлов? - PullRequest
3 голосов
/ 11 мая 2009

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

Как я могу сделать это с PHP?

Ответы [ 7 ]

15 голосов
/ 11 мая 2009

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

Так что просто переименуйте его в какую-нибудь схему по вашему собственному замыслу. Это мой совет.

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

2 голосов
/ 11 мая 2009
1 голос
/ 01 сентября 2011

Предположим, вы отправляете файл из формы, где у вас есть ввод с именем incomingfile, например:

<input type="file" id="incomingfile" name="incomingfile" />

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

$new_depured_filename = strtolower(preg_replace('/[^a-zA-Z0-9_ -.]/s', '_', $_FILES["incomingfile"]["name"]));
copy($_FILES["incomingfile"]["tmp_name"], 'my_temp_directory/'.$new_depured_filename);

Используя следующий фрагмент кода, я проверяю, существует ли файл, если да, я нахожу новое имя и, наконец, копирую его. Например, если я хочу записать файл с именем myimage.jpg, и он уже существует, я переименую ожидающий файл в myimage__000.jpg. Если это также существует, я переименовываю ожидающий файл в myimage__001.jpg и так далее, пока не найду несуществующее имя файла.

$i=0; // A counter for the tail to append to the filename
$new_filename = $new_depured_filename;
$new_filepath='myfiles/music/'.$new_filename;
while(file_exists($new_filepath)) {
    $tail = str_pad((string) $i, 3, "0", STR_PAD_LEFT); // Converts the integer in $i to a     string of 3 characters with left zero fill.
    $fileinfos = pathinfo($new_filepath); // Gathers some infos about the file
    if($i>0) { // If we aren't at the first while cycle (where you have the filename without any added strings) then delete the tail (like "__000") from the filename to add another one later (otherwise you'd have filenames like myfile__000__001__002__003.jpg)
        $previous_tail = str_pad((string) $i-1, 3, "0", STR_PAD_LEFT);
        $new_filename = str_replace('__'.$previous_tail,"",$new_filename);
    }
    $new_filename = str_replace('.'.$fileinfos['extension'],"",$new_filename); // Deletes the extension
    $new_filename = $new_filename.'__'.$tail.'.'.$fileinfos['extension']; // Append our tail and the extension
    $new_filepath = 'myfiles/music/'.$new_filename; // Crea il nuovo percorso
    $i++;
}

copy('my_temp_directory/'.$new_depured_filename, $new_filepath); // Finally we copy the file to its destination directory

unlink('my_temp_directory/'.$new_depured_filename); // and delete the temporary one

Используемые функции:
strtolower
preg_replace
копия
file_exists
str_pad
PathInfo
str_replace
разъединить

1 голос
/ 11 мая 2009

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

1 голос
/ 11 мая 2009

Не используйте file_exists () по той причине, что он возвращает true (по крайней мере, в системах * nix, поскольку каталоги являются специализированными файлами), если значение является каталогом. Вместо этого используйте is_file ().

Например, скажите, что что-то не получается, и у вас есть строка вроде:

$path = "/path/to/file/" . $file; // Assuming $file is an empty value, if something failed for example
if ( true === file_exists($path) ) { echo "This returns true"; }
if ( true === is_file($path) ) { echo "You will not read this"; }

Это вызвало у меня несколько проблем в прошлом, поэтому я всегда использую is_file (), а не file_exists ().

0 голосов
/ 11 мая 2009

Я использую

$file_name = time() . "_" . $uploaded_file_name;
0 голосов
/ 11 мая 2009

Чтобы проверить, существует ли файл, вы можете использовать функцию file_exists.

Чтобы вырезать имя файла, вы можете использовать функцию pathinfo.

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