Se connecter avec
S'enregistrer | Connectez-vous

[Résolu] [PHP] renommer un fichier si il existe déja

Dernière réponse : dans Programmation

Hello, je viens de faire un uploader d'images, disponible a cetet adresse.

Mais j'aimerais mettre en place un code qui renomme l'image si celle ci existe déja dans le répértoire d'upload. Exemple, si j'uplaode salut.png et que je le réuploade une deuxieme fois, j'aurais salut154.png.

Pour cela j'ai mis en place ceci :



$filename = '/upload/$nom_fichier';
$rand = 'rand(5, 50)';

if (file_exists($filename)) {
rename("/upload/$nom_fichier", "/upload/$nom_fichier$rand");
} else {
}


Mais marche pas :(  le code source est disponible a cetet adresse

J'espère que vous pourrez m'aider.

Bonne journée
Lassé par la pub ? Créez un compte

Bien entendu, tu ne peux pas faire un rename alors que le fichier n'est pas encore copié.
Tu devrais plutôt faire:
  1. if (file_exists("/upload/$nom_fichier")) {
  2. $nom_fichier = $rand."_".$nomfichier;
  3. }

D'ailleurs, je passe ton $rand avant pour ne pas te faire perdre l'extension.

Et un petit truc utile: lorsqu'on fait un système d'upload de fichiers destinés à être archivés, il est intéressant de TOUJOURS ajouter un identifiant unique, soit en utilisant uniqid() soit en faisant précéder le nom de (par exemple) date("YmdHis_").
Cela t'évite d'avoir à vérifier chaque fois si le fichier existe déjà, d'autant plus que le rand() peut te renvoyer plusieurs fois la même valeur.

si je comprends bien, tu veux renommer l'ancien puis copier le nouveau?
si c'est le cas, faudrait enlever le else

EDIT:
crazycat@idn a dit :
Bien entendu, tu ne peux pas faire un rename alors que le fichier n'est pas encore copié

si file_exists () retourne vrai, il peut, mais il va renommer l'ancien :) 
enfin ca depend de ce qu'il a voulu faire

tu le met à la place de ton:
  1. if (file_exists($filename)) {
  2. rename("/upload/$nom_fichier", "/upload/$nom_fichier$rand");
  3. } else {
  4. }

En fait, ça permet de changer le nom de destination *avant* la copie du fichier temp vers sa place définitive.
Je présume que le script initial n'est pas de toi...

tout d'abord, "ça ne marche pas" n'est pas constructif.
Ensuite, tu devrais plutôt utiliser la fonction dédiée au déplacement de fichiers uploadés (move_uploaded_file()) plutôt que copy().

Et tu as une erreur (que je n'avais pas relevée):
  1. $rand = 'rand(5, 50)';

depuis quand on met des ' ' autour d'un appel de fonction?

Il ne veut toujours pas me modifier le fichier que je tente d'uploader uen deuxieme fois !

Acutellement j'ai ca :

  1. $rand = rand(5, 50);
  2.  
  3. if (file_exists("/upload/$nom_fichier" )) {
  4. $nom_fichier = $rand."_".$nomfichier;
  5. }


J'ai msi a jour le fichier texte pour avoir une vue d'ensemble.

Pour le move_uploaded_file, je le mettrais surement lorsque mon problème sera réglé.

dans la meme optique:
  1. $filename = '/upload/$nom_fichier';

une variable entre ' ' n'est pas intérprétée, mais j'ai vu que ce n'etait pas pareil sur le upload.txt
EDIT:
d'ailleurs rand n'est pas affectée dans upload.txt à part si c'est le cas dans le include du menu

Jeoffrey54 a dit :
Acutellement j'ai ca :
  1. $rand = rand(5, 50);
  2. if (file_exists("/upload/$nom_fichier" )) {
  3. $nom_fichier = $rand."_".$nomfichier;
  4. }


Tu pourrais AU MOINS corriger mes fautes de frappe.
$nom_fichier = $rand."_".$nomfichier; <-- plutôt $nom_fichier

Arf, j'ai été un peu trop vite. Bon jviens de revoir un peu tout ca, j'ai regardé un peu les variables, j'ai ca pour l'instant :

  1. $rand = rand(5, 50);
  2.  
  3. if (file_exists("/upload/$nom_fichier" )) {
  4. $nom_fichier = $rand."_".$nom_fichier;
  5. }


Mais pas moyen d'ajouter ces nombre au début :( 

fais des affichages de debug pour savoir ce qui échoue.
Et je te signale une petite erreur en passant:
  1. copy($ftmp,"upload/".$nom_fichier);

Un peu partout, tu utilises le répertoire /upload (donc à la racine de ton site) et là tu utilises un sous-répertoire du répertoire courant.
Donc, si ton script n'est pas à la racine de ton site, tu n'up pas dans le bon répertoire.

par exemple:
  1. if (file_exists("/upload/$nom_fichier" )) {
  2. echo "-- On a déjà le fichier ".$nom_fichier." --<br />\n";
  3. $rand = rand(5, 50);
  4. echo "-- On a créé le préfixe ".$rand." --<br />\n";
  5. $nom_fichier = $rand."_".$nom_fichier;
  6. echo "-- Le nouveau nom de fichier est ".$nom_fichier." --<br />\n";
  7. }

Tu noteras que j'ai passé le rand() dans le if pour éviter de générer inutilement la variable.

ah, si c'est une question de config, je connaissais pas, et du coup, si on veut acceder à un rep en dehors du site, ca se passe comment?

EDIT: sur une config standard, ca a l'air d'etre la racine du disque...
si tu connais l'element de config pour rendre / = racine du site, je suis interessé

tout est affaire de configuration, je te conseille de jeter un oeil sur les variables de php.ini:
http://fr.php.net/manual/fr/ini.core.php#ini.include-pa... ainsi que les 2 suivantes (doc_root et user_dir).

Et à moins d'être sur un serveur qu'on maitrise parfaitement (un dédié), il est impossible d'accéder à un répertoire qui n'appartient pas à son espace web (ou espace personnel, selon la configuration).

Regarde le fichier texte à cette adresse

J'ai noté aucune amélioration, ca n'affiche pas les echo que tu a mis.

  1. if (file_exists("/upload/$nom_fichier" )) {
  2. echo "-- On a déjà le fichier ".$nom_fichier." --<br />\n";
  3. $rand = rand(5, 50);
  4. echo "-- On a créé le préfixe ".$rand." --<br />\n";
  5. $nom_fichier = $rand."_".$nom_fichier;
  6. echo "-- Le nouveau nom de fichier est ".$nom_fichier." --<br />\n";
  7. }

C'est une rêgle quasi vitale à connaitre: toujours adopter la même convention d'écriture pour les chemins des fichiers.

Et encore une fois, je t'invite à utiliser autre chose que le rand() pour préfixer tes fichiers, comme:
  1. $rand = uniqid(rand());

tout est dit dans la doc :) 
rand() génère un nombre "aléatoire" entre 0 et 1. Dans ton cas (rand(5,50)), il va générer un nombre au hazard entre 5 et 50, ce qui veut dire que tu pourras au maximum avoir 45 images du même nom.
De plus, rien n'interdit à rand() de sortir plusieurs fois le même chiffre, et tu ne fais qu'une seule vérification, donc à terme tes probabilités d'écraser un fichier déjà existant sont assez énormes*.
uniqid() génère un nombre de 13 chiffres basé sur microtime() (les millisecondes système) et le préfixe donné (dans notre cas, rand()).
Les probabilités d'avoir deux fois le même uniqid de généré sont donc beaucoup plus faibles.

* Si tu savais le nombre de personnes qui vont envoyer un fichier appelé "logo.png", "avatar.gif" ou "moi.jpg"...

je m'incruste avec mes questions mais crazy, effectivement j'avais jamais utilisé ces directives et comme je suis curieux :)  je les ai téstées.
ca ne m'a pas rendu le / = racine du site, par contre ca m'empeche d'aller lire un fichier en dehors du repertoire que j'ai indiqué
ex:
  1. safe_mode = On
  2. doc_root = "/var/www/html/php"
  3. user_dir = "public_php"


j'ai raté quelque chose?

C'est le safe_mode qui te bloque.
Concernant le / qui représenterait la racine du site, je crois avoir fait une petite erreur (par omission): c'est la config d'apache qui permet cela.
Maintenant, je ne peux pas t'en dire plus car c'est quelque chose que j'ai rencontré sur le serveur d'un client (je me suis cassé les dents dessus pendant des heures) et je n'ai jamais tenté de le reproduire car c'est très chiatique à gérer (en temps que webmaster).

crazycat@idn a dit :
soit en utilisant uniqid() soit en faisant précéder le nom de (par exemple) date("YmdHis_").

okinou a dit :
moi je renomme avec l'id de la photo up (enregistre dans mysql) en md5 ou, avec la date entiere :
yyyymmddHis

le md5() n'est pas bijectif, tu peux avoir 2 md5 identiques pour des chaines différentes.
La date est à priori unique et en plus elle permet un tri aisé.
Expert Programmation

je n'avais pas tout lu, la fleem, j'exposais ma méthode ;) 

pour le md5, peut etre si tu as des millions de photos, mais pour un usage personnel, sachant qu'une chaine aura 32 caractere, pour l'espoir de retombé avec la meme clé est quasi impossible.
Expert Programmation

ON VIENT DE TE DIRE QUE C'EST NORMAL, comment espère tu avoir une chaine unique si tu n'as que 2 caractère dans ta chaine ?

Ici avec uniqid tu as 22 caractère, md5 en créer 32.

SECONDE SOLUTION, ET DERNIERE FOIS QUE JE ME REPETE, tu utilises la DATE :

date("YmdHis_" )

ce qui te fera :

20070213010534 soit 14 caractere pour l'heure : 13 fevrier 2007 01:05:34 sec

Lis un peut ce que l'on te dit bordel !

Et pour finir, la doc, c'est magique :

http://fr.php.net/manual/fr/function.md5.php
http://fr.php.net/manual/fr/function.uniqid.php
http://fr.php.net/manual/fr/function.date.php
Lassé par la pub ? Créez un compte
Tom's guide dans le monde