Quelle est la meilleure pratique pour nommer les images téléchargées?

15

Supposons que j'ai un formulaire dans mon application Web où les utilisateurs peuvent télécharger une photo de profil.

J'ai peu d'exigences concernant la taille du fichier, les dimensions, etc., mais lorsque l'utilisateur télécharge l'image, comment dois-je les nommer sur mon système? Je suppose que cela devrait être cohérent et aussi unique.

Peut-être un GUID?

a5c627bedc3c44b7ae7c06a44fb3fcf8.jpg

Un horodatage?

129899740140465735.jpg

Un hachage? Ex: md5

b1a9acaf295cf14ffbc5b6538294562c.jpg

Existe-t-il un moyen standard ou recommandé de procéder?

Rowan Freeman
la source
7
Si votre objectif est de stocker une seule image de profil par utilisateur, certains diront que le choix évident serait de nommer le fichier de la même manière que l'ID des utilisateurs.
Alan Barber le
l'horodatage n'est pas une bonne idée, car DateTime.Now n'est actualisé que toutes les 15 ms. Il y a un risque élevé de collision, par exemple lors d'un chargement en masse, de demandes en file d'attente, etc.
jhexp

Réponses:

27

Vous devez essayer d'atteindre deux objectifs: l'unicité et l'utilité.

L'utilisation d'un GUID garantit l'unicité, mais un jour, les fichiers peuvent se détacher de leur source d'origine, et vous aurez alors des ennuis.

Ma solution typique consiste à incorporer des informations cruciales dans le nom de fichier, telles que l'ID utilisateur (s'il appartient à un utilisateur) ou la date et l'heure téléchargées (si cela est significatif), ou le nom de fichier utilisé lors du téléchargement.

Cela peut vraiment sauver votre peau un jour, lorsque les informations intégrées dans le nom de fichier vous permettent, par exemple, de récupérer d'un bug ou de la suppression accidentelle d'enregistrements. Si tout ce que vous avez, ce sont des GUID et que vous perdez le catalogue, vous aurez une sacrée tâche de nettoyage.

Par exemple, si un fichier "My Holiday: Florida 23.jpg" est téléchargé, par userID 98765, le 04/04/2013 à 12:51:23, je le nommerais quelque chose comme ça, en ajoutant une chaîne aléatoire ad8a7dsf9:

20130404125123-ad8a7dsf9-98765-my-holiday-florida-23.jpg

  • L'unicité est assurée par la date et l'heure, et une chaîne aléatoire (à condition qu'elle soit correctement aléatoire à partir de / dev / urandom ou CryptGenRandom.
  • Si le fichier est détaché, vous pouvez identifier l'utilisateur, la date et l'heure et le titre.
  • Tout est plié en minuscules et tout ce qui n'est pas alphanumérique est supprimé et remplacé par des tirets, ce qui rend le nom de fichier facile à manipuler à l'aide d'outils simples (par exemple, aucun espace pouvant confondre des scripts mal écrits, pas de deux-points ou d'autres caractères interdits sur certains systèmes de fichiers , etc).
Ben
la source
7
Par souci de propreté, je recommanderais de créer des répertoires distincts par ID utilisateur afin que si vous supprimez un utilisateur, vous n'aurez pas à chercher toutes ses photos. - donc98765/20130404125123-ad8a7dsf9-my-holiday-florida-23.jpg
Shadur
1
Théoriquement, l'unicité n'est pas fournie par la chaîne aléatoire.
Kolyunya
4
@Kolyuny, c'est vrai, dans le sens où l'unicité globale garantie n'est pas une propriété que même les GUID ont dans la vie réelle (même les guides v1 sont interrompus en raison de la publication d'adresses MAC en double). Tout ce que vous pouvez obtenir est une probabilité statistique d'unicité. Mais vous pouvez garantir l'unicité en vérifiant si le fichier existe déjà (en utilisant atomiquement CreateFileavec CREATE_NEW), et en utilisant un caractère aléatoire différent si c'est le cas.
Ben
`` Tout est plié en minuscules et tout ce qui n'est pas alphanumérique est supprimé et remplacé par des tirets '', je garderais le casse mixte, supprimez tous les caractères non alphanumériques et remplacez-le par les scores inférieurs, sauf le dernier tiret
tgkprog
4

Vous ne voulez pas mettre l'accent sur les applications (telles que l'Explorateur) et le faire planter lorsque vous ouvrez le répertoire. Bien qu'il soit peu probable que vous mettiez l'accent sur le système de fichiers réel, vous devez en tenir compte si vous stockez des milliers de fichiers.

Si vous prévoyez de stocker des milliers de fichiers, ma suggestion est de partitionner en dossiers. Par exemple upload\silo001, upload\silo002etc. Vous pouvez soit équilibrer vos fichiers, soit attendre qu'un dossier atteigne un certain nombre de fichiers, puis en créer un autre.

En ce qui concerne la dénomination, je nomme toujours un fichier avec un GUID car il est globalement unique. Je tire l'extension du téléchargement et définit l'extension du fichier pour qu'elle corresponde, mais le nom réel est défini à partir d'un nouveau Guid.

Si vous faites cela en conjonction avec un SGBDR et ont plusieurs catégories, à savoir les produits, catégories, etc. vous pourriez avoir upload\products, upload\categorieset ainsi de suite, et vous pouvez utiliser l'ID de ligne que le nom de fichier.

En termes de bonnes pratiques, moi aussi j'ai regardé dans le passé et je n'ai rien trouvé. J'ai trouvé ce qui précède tout en discutant avec certains de mes développeurs.

Sam
la source
2

Dans l'une des solutions sur lesquelles j'ai travaillé il y a des années, nous avons fait ceci: sous-dossiers pour une partie de l'ID utilisateur, donc si votre ID utilisateur était 232950192

nous aurions des sous-dossiers images / 23/29/50/192/232950192

dans le dossier final ont des dossiers pour les albuns et les images de profil, etc.

Mais nous sauvegardons également tout dans la base de données et le conservons dans le système de fichiers pour un accès rapide au serveur Web (qui a également la mise en cache)

Quoi qu'il en soit, l'image finale aurait le nom de l'image d'origine. Nous n'avions pas besoin de conserver les versions. Mais pour ce qui peut garder plus de sous-dossiers sous les noms d'album finaux ou dans la base de données avec un identifiant de version. besoin de le penser car une fois en production, il serait difficile de changer les choses sans des corrections longues et sujettes aux erreurs dans la structure actuelle

Il est très facile de créer un sous-dossier en java et de créer un fichier dedans:

    File folder = new File(pathwithslashes);// like "images/23/29/50/192/232950192"
    folder.mkdirs();
    File imgFile = new File(folder, name);
    //Now get output stream etc

Pour obtenir l'horodatage dans les sous-dossiers: SimpleDateFormat sdf = new SimpleDateFormat ("/ yyyy / MM / dd /"); pathwithslashes = pathwithslashes + sdf.format (maintenant); // est maintenant un dossier de fichier util.Date = nouveau fichier (pathwithslashes);

Dot net /programming/5482230/c-sharp-equivalent-of-javas-mkdirs

tgkprog
la source
+1 pour suggérer des répertoires imbriqués. Je pense que c'est important à considérer car différents systèmes de fichiers peuvent rencontrer des problèmes de performances lorsque les dossiers contiennent "trop" de fichiers: stackoverflow.com/questions/197162/… , support.microsoft.com/kb/130694/en-us , etc.
deizel
1
Oui, sur un autre système, l'un des blocages du serveur Web s'est produit lorsque nous avons essayé de rmdir sur un répertoire contenant plus de 400 000 fichiers. nous avions plus de dossiers comme celui-ci. alors j'ai utilisé un programme personnalisé qui a appelé dir / p pour obtenir quelques fichiers à supprimer à la fois. a pris quelques heures mais pas de temps d'arrêt :)
tgkprog
1

Je recommanderais d'utiliser juste md5 ou quelque chose d'équivalent conceptuel. En renommant les fichiers en résumant leur contenu, vous n'accordez pas seulement l'unicité (mettez toujours les images en cache aussi longtemps que possible, et avec un changement de nom basé sur le contenu, eh bien, avec un bon, vous pouvez mettre les images en cache pratiquement pour toujours).

De plus, ce n'est pas grave, mais ce n'est pas un cas purement hypothétique lorsque différents utilisateurs téléchargent exactement la même image. Tout juste sorti de la boîte, vous aurez une petite optimisation du stockage des données.

En ce qui concerne toute autre proposition: quant à moi, je suis un adversaire ferme de conserver toute sorte d'informations auxiliaires dans un nom de fichier. Quand j'étais beaucoup plus jeune (et un peu plus mince :), j'étais un développeur Perl et j'avais l'habitude douteuse de stocker autant d'informations auxiliaires dans le nom de fichier que le bon sens me le permettait, car les fonctionnalités de modèle de chaîne Perl sont impressionnantes. Et je suis arrivé à la conclusion que, en parlant de développement Web, il est toujours préférable de conserver les données associées au fichier séparément du nom de fichier.

Gardez à l'esprit que de nos jours, lorsque les interfaces mobiles dominent, le nom de fichier réel est une chose moins importante qu'il y a 5, 10 ans. Mais même si cela est crucial dans le contexte de votre application, vous pouvez toujours impliquer de la magie de la vieille école avec un Content-Disposition: attachment; filename="pretty_file_name.jpg"en-tête HTTP impliquant , en construisant le nom de fichier approprié que vous souhaitez. En outre, les navigateurs modernes ouvrent la voie au nouvel attribut HTML5, le téléchargement . Je ne pense pas que voir un nom d'image "lisible par l'homme" soit une chose à laquelle vous devriez penser dans la majorité des cas.

UPD: Une modification peut être effectuée afin de ne pas avoir trop de fichiers dans un répertoire - il suffit de prendre les 3 premières lettres et de créer dir.

shabunc
la source
1
est-ce que md5 est vraiment unique?
I.devries
@ I.devries, je ne suis pas un spécialiste, mais pour autant que je sache, c'est assez bon pour cela. Surtout si vous vérifiez en outre la taille du fichier, car un bon algorithme de hachage garantit en fait que les entités de même taille auront moins probablement une collision - stackoverflow.com/questions/2442632/…
shabunc
-1

Les risques de collisions avec quelque chose comme sha4 sont infinitésimaux. Si vous combinez le hachage avec l'ID utilisateur ou même une date simple, encore moins.

Evan Zamir
la source