web-dev-qa-db-fra.com

Stockage d'images téléchargées par l'utilisateur

Quelle est la pratique habituelle pour gérer les photos téléchargées par l’utilisateur et les stocker dans la base de données et le serveur?

Pour une image de profil utilisateur:

  1. Après avoir reçu le fichier image de l'utilisateur, renommez le fichier en <image_id>_<username>
  2. Déplacer l'image vers /images/userprofile
  3. Ajoutez un nom de fichier img à une table users contenant les détails de leur profil, comme first_name, last_name, age, gender, birthday

Pour une image pour une révision faite par l'utilisateur:

  1. Après avoir reçu le fichier image de l'utilisateur, renommez le fichier en <image_id>_<review_id>
  2. Déplacer l'image vers /images/reviews
  3. Ajoutez un nom de fichier img à une table reviews contenant les détails de leur profil, comme review_id, review_content, user_id, score.

Question 1: Comment dois-je procéder pour stocker les noms de fichiers d'images si l'utilisateur peut télécharger plusieurs photos pour un commentaire particulier? Sérialiser?

Question 2: Ou avez-vous une autre table review_images avec des colonnes review_id, image_id, image_filename uniquement pour le suivi des images? Est-ce que faire un JOIN lors du rappel du image_filename de ce tableau ralentira sensiblement les performances?

Question: Toutes les images doivent-elles être stockées dans un seul dossier? Y aura-t-il un problème lorsque nous aurons 100 000 photos dans le même dossier?

Existe-t-il un moyen plus efficace de procéder?

5
Nyxynyx

Réponse courte: inutile de stocker le nom de fichier de l'image dans la base de données. Il suffit de renommer le fichier téléchargé en theirusername.jpg et de le stocker dans /uploads/users/. Réponse plus longue ci-dessous.


Question 1: Comment dois-je procéder pour stocker les noms de fichiers d'images si l'utilisateur peut télécharger plusieurs photos pour un commentaire particulier? Sérialiser?

Vous pourriez:

  1. Séparez les noms de fichiers par une virgule et stockez-les dans un seul champ images dans la table review. Lorsque vous récupérez des images à afficher, scindez la chaîne images par une virgule et passez en boucle sur ce tableau pour les disposer. (S'il n'y a qu'une seule image, cela fonctionnera toujours.)

  2. Créez une table séparée appelée images ou review_images et stockez chaque image sur sa propre ligne, comme vous le suggérez dans votre deuxième question.

Question 2: Ou avez-vous une autre table review_images avec des colonnes review_id, image_id, image_filename uniquement pour le suivi des images? Le fait de faire une jointure lors de la récupération du nom de fichier image de cette table ralentira-t-il sensiblement les performances?

Il est peu probable que vous perceviez des difficultés de performance en utilisant un simple JOIN. Vous pouvez nier ou réduire vos petits succès en termes de performances en mettant en cache des requêtes et en servant du code HTML statique.

Question 3: Toutes les images doivent-elles être stockées dans un seul dossier?

Je vous suggérerais soit:

  1. Créez un seul dossier pour chaque utilisateur de votre répertoire /uploads/ lors du téléchargement de son premier fichier.
  2. Créez un nouveau dossier chaque mois (automatiquement dans le cadre de votre script de téléchargement) et téléchargez des images à cet endroit. C’est ce que WordPress fait par défaut.

Cela réduit les risques de limite de répertoires sur le nombre de fichiers.

Y aura-t-il un problème lorsque nous aurons 100 000 photos dans le même dossier?

Peut-être, en fonction du système de fichiers utilisé par votre serveur. Il y a des limites au nombre de fichiers que vous pouvez avoir dans un seul répertoire. FAT32, par exemple, a une limite de 65 535 fichiers par dossier. Voir "Combien de fichiers dans un répertoire sont trop nombreux?" sur Stack Overflow. Notez que l'utilisation des dossiers, comme je le suggère ci-dessus, réduit le risque de dépasser les limites du répertoire.

Y a-t-il un moyen plus efficace de s'y prendre?

Vous n'avez pas du tout besoin de stocker des données d'image dans votre base de données si vous suivez une convention simple. Lorsqu'un utilisateur télécharge une image de profil, par exemple, vous pouvez la renommer en profile.jpg, puis la stocker dans /uploads/users/username/. Maintenant, vous avez seulement besoin du nom d'utilisateur de l'utilisateur pour récupérer son image de profil. Vous n'avez plus besoin de stocker une référence à l'image dans la base de données. (Ou vous pouvez simplement nommer l'image theirusername.jpg et la stocker dans /uploads/users/ - choisissez la convention qui vous convient le mieux.)

De même, lorsque l'utilisateur télécharge des images pour une révision, vous pouvez les stocker dans un dossier nommé /uploads/reviews/13/. Le numéro 13 à la fin serait l'ID de révision - l'ID unique de cette révision tel qu'il est stocké dans la table de base de données. Pour afficher ces images, il vous suffit d’obtenir l’ID de révision pour récupérer ces images. (Pour savoir quelles images se trouvent dans un dossier, vous pouvez scanner le répertoire. Avec PHP, vous utilisez scandir () , par exemple.)

2
Nick

Stockez les informations sur l'image dans la base de données (nom d'utilisateur, identifiant de l'image, nom de fichier) et saisissez-les avec un JOIN.

Ce fil sur Stack Overflow discute de la même idée, bien que je ne puisse pas trouver le fil exact que je voulais référencer, ce qui donne de meilleures explications. Michael Andrews explique dans son blog quelques-unes des pratiques actuelles sur la manière de mettre en œuvre un système comme celui-ci ...

L'idée de base est que vous stockez l'image en hachant son contenu et en utilisant ce hachage comme nom de fichier.

  • Supposons que votre utilisateur télécharge "LazyCat.jpg" en tant qu'image.
  • Le hachage SHA1 pour cette image pourrait être 'ac17c9e81fc3789ab6b8c1f3325d789e9aa3daaf'
  • Sur votre serveur, vous avez un répertoire d’images 'images'. Les images sont les sous-répertoires des premiers chiffres du hachage, par exemple. '/ images/0000', '/ images/0001 /', ..., '/ images/a3df /', ..., '/ images/ffff /'
  • Suivez ce modèle (pour réduire le nombre de fichiers dans un répertoire plus petit) et enregistrez votre fichier dans le répertoire correspondant, dans ce cas '/ images/ac17/ac17c9e81fc3789ab6b8c1f3325d789e9aa3daaf'
  • Dans votre base de données, enregistrez l'ID utilisateur et le nom de fichier correspondant.

Si plusieurs personnes téléchargent la même image, celle-ci ne sera stockée qu'une seule fois sur le serveur. Chaque fois que votre base de données ne contient plus de références à ce nom de fichier, vous êtes libre de le supprimer.

2
dmsnell