Votre question

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

Tags :
  • Programmation
Dernière réponse : dans Programmation
12 Février 2007 14:17:38

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

Autres pages sur : resolu php renommer fichier existe

a c 145 L Programmation
12 Février 2007 14:30:34

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.
12 Février 2007 14:31:46

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
Contenus similaires
12 Février 2007 14:34:55

Donc mon

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


Je le met ou ?

c'est pas pour renommer l'ancien, mais celui qu'on cherche a uploader !
a c 145 L Programmation
12 Février 2007 14:38:48

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...
12 Février 2007 14:50:10

Ca ne marche pas :( 

J'ai mis a jour le fichier upload.txt
a c 145 L Programmation
12 Février 2007 15:16:57

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?
12 Février 2007 15:29:06

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é.
12 Février 2007 15:29:22

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
a c 145 L Programmation
12 Février 2007 15:40:09

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
12 Février 2007 15:43:39

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 :( 
a c 145 L Programmation
12 Février 2007 16:22:14

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.
12 Février 2007 16:52:03

Mon site est a la racine, donc aucun problème, mais sinon c'est quoi les affichages de debug ?
a c 145 L Programmation
12 Février 2007 16:58:59

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.
12 Février 2007 16:59:49

il y a une difference qd meme, a part si ton site est à la racine de ton disque, parce qu'en l'occurence, le chemin ( et donc le "/") dans file_exists et cie s'applique à l'arboressence du disque et non du site.
a c 145 L Programmation
12 Février 2007 17:05:24

NON! Du moins pas toujours.
le / s'applique très souvent au document_root et non pas au root de la machine (si la configuration est bien faite).
Mais il est vrai qu'il vaut mieux utiliser un chemin relatif ou un chemin physique réel.
12 Février 2007 17:08:36

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é
a c 145 L Programmation
12 Février 2007 17:15:25

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).
12 Février 2007 17:21:47

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. }
a c 145 L Programmation
12 Février 2007 17:32:59

dans ce cas, c'est que tu ne rentres pas dans ton if.
Conclusion: vire le / initial devant tout tes "upload".
12 Février 2007 17:38:53

Crazycat, je t'aime ! (l)

J'ai supprimé les / devant upload et ca marche ;) 

Encore merci :D 
a c 145 L Programmation
12 Février 2007 17:43:20

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());
12 Février 2007 17:47:22

quel est la différence ?
a c 145 L Programmation
12 Février 2007 17:55:08

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"...
12 Février 2007 17:55:33

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?
a c 145 L Programmation
12 Février 2007 18:00:24

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).
12 Février 2007 18:06:16

le safe_mode etait volontaire
c'etait le / que je comprenais pas, effectivement je crois que php bloque l'acces, mais ne reaffecte pas le /
je connaissais pas doc_root, c'est toujours bon à savoir ;) 
12 Février 2007 18:23:03

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


yyyymmddHis

ou

time()
a c 145 L Programmation
12 Février 2007 18:28:14

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é.
12 Février 2007 18:34:28

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.
a c 145 L Programmation
12 Février 2007 19:31:20

Oui, bien sûr, je parle dans l'absolu.
En règle générale et pour un usage limité, on peut très bien utiliser md5 et sha1.
L'avantage de la méthode par date/heure est un classement simplifié et logique.
12 Février 2007 19:37:53

J'ai essayé avec $rand = uniqid(rand());

et il m'a donné le préfixe 66346640745d0b36483953.

Ca fait un peu beaucoup non ? Comment le réduire ?
12 Février 2007 20:04:43

si tu le reduis, tu perds son caractere unique
si ca te parait bcp, utilise l'heure comme indiqué plus haut
12 Février 2007 20:05:44

Ok, mais tu trouves pas que ca fait grand comme nom ?
12 Février 2007 20:12:01

c'etait une solution possible
à toi de voir ce qui te convient
12 Février 2007 20:16:12

J'ai mis $rand = rand(5, 1000);

J'ai plus de 900 possibilités, et puis ce n'est qu'un site perso, j'utiliserai uniqid(rand()); si je m'aperçois que mon uploader est beaucoup utilisé ;) 
a c 145 L Programmation
12 Février 2007 22:26:38

le problème reste le même: rand() ne t'assure pas que tu auras un identifiant jamais utilisé.
Rien n'empèche que le même chiffre sorte 3 fois sur 10 tirages.
12 Février 2007 23:10:53

tout à fait, pour aucune enmerde, utilise sha1 md5 ou les date.
13 Février 2007 00:28:09

Je vois ce que tu veux dire Crazycat, je vais remettre uniqid(rand()); mais n'y a t'il pas moyen d'afficher moins de nombres ? Car 66346640745d0b36483953 ca fait beaucoup non ?
13 Février 2007 01:06:44

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
13 Février 2007 10:50:39

C'est bon calme toi !

Problème résolu, merci et @+
13 Février 2007 10:53:36

Je suis calme, cool, zen, exomile...
13 Février 2007 10:57:49

au moins ca a le mérite d'être clair :D 
pour le résolu, c'est dans le titre qu'on le place
Tom's guide dans le monde
  • Allemagne
  • Italie
  • Irlande
  • Royaume Uni
  • Etats Unis
Suivre Tom's Guide
Inscrivez-vous à la Newsletter
  • ajouter à twitter
  • ajouter à facebook
  • ajouter un flux RSS