web-dev-qa-db-fra.com

PHP stocker des images dans MySQL ou pas?

J'ai construit une petite application Web dans PHP où les utilisateurs doivent d'abord se connecter. Une fois qu'ils se sont connectés, j'ai l'intention d'afficher une petite vignette dans le cadre de leur "profil".

Je devrai vérifier que l’image est au-dessous d’une certaine taille pour conserver de l’espace, ou pour obtenir une résolution particulière, ou les deux, voire même utiliser quelque chose comme l’image magick pour la réduire.
Je ne sais pas quelle est la meilleure approche pour cela, toutes les idées sont les bienvenues.

En outre, j'essayais de déterminer s'il était préférable de stocker l'image dans la table users de MySQL sous forme de blob, ou peut-être une table images séparée avec un identifiant unique, et de stocker simplement l'ID d'image approprié dans la table users, ou enregistrez simplement le fichier téléchargé sur le serveur (via une page de téléchargement également) et enregistrez le fichier sous le nom theUsersUniqueUsername.jpg. Meilleure option?

J'ai trouvé un tutoriel sur la sauvegarde d'images sur mysql ici: http://www.phpriot.com/articles/images-in-mysql

Je ne suis qu'un programmeur amateur et je n'ai jamais rien fait de tel auparavant. Des exemples et/ou beaucoup de détails sont donc grandement appréciés.

31
occhiso

Cela dépend toujours du contexte, mais généralement, je stocke une image utilisateur sur le système de fichiers dans un dossier appelé /content/user/{user_id}.jpg et j'essaie de gêner le moins possible la base de données.

40
Mario

Je recommanderais de stocker l'image en tant que fichier et d'avoir ensuite l'URI du fichier dans la base de données. Si vous stockez toutes les images dans la base de données, vous pourriez avoir des problèmes de redimensionnement ultérieurement.

Découvrez cette réponse aussi:

Les conseils de Microsoft concernant SQL Server consistaient autrefois, en termes de vitesse et de taille, à stocker des images dans le système de fichiers, avec des liens dans la base de données. Je pense qu'ils ont un peu adouci leurs préférences, mais je considère tout de même que c'est une meilleure idée de taille, car cela ne prendra pas de place dans la base de données.

23
Philip Morton

Les frais généraux liés à l'utilisation de BLOB sont bien moindres que ce que la plupart des gens voudraient vous faire croire, surtout si vous les configurez correctement. Si vous utilisez un serveur distinct exécutant simplement la base de données pour stocker des fichiers binaires, vous ne pouvez en fait utiliser aucun système de fichiers et éviter toute surcharge du système de fichiers.

Cela dit, le moyen le plus simple/le meilleur, à moins de disposer de quelques serveurs, consiste à les stocker dans le système de fichiers.

  • Ne stockez pas l’URL absolue du fichier dans votre base de données, mais seulement la partie unique (et éventuellement un dossier ou deux), par exemple. 2009/uniqueImageName.jpg ou simplement uniqueImageName.jpg. Ensuite, dans vos pages, ajoutez simplement l’hôte et d’autres dossiers au premier plan. Ainsi, vous disposerez d’une certaine souplesse pour déplacer vos images: il vous suffira de modifier une ligne ou deux dans votre écran. Page PHP/ASP.NET.

  • Il n’est pas nécessaire de stocker en dehors de la racine du document pour des raisons de sécurité - un fichier .htaccess avec DENY FROM ALL fonctionnera de la même manière et offrira plus de flexibilité.

  • Inutile de "shuter" autant les images pour des raisons de sécurité, créez simplement une page getImage.php ou quelque chose du genre, puis au lieu d'insérer l'URL réelle dans la src de la image, utilisez quelque chose comme getImage.php?file=uniqueImageName.jpg. Ensuite, le fichier getImage.php peut vérifie si l'utilisateur est autorisé et récupère l'image (ou non).

  • Utilisez un nom qui est garanti pour être unique (de préférence un entier, c’est-à-dire une clé primaire) lors du stockage, certains systèmes de fichiers (c’est-à-dire Windows) ne respectent pas la casse, donc JoeBloggs.jpg et joebloggs.jpg sont uniques pour la base de données, mais pas pour le système de fichiers. donc on va écraser un autre.

  • Utilisez une table distincte pour les images et stockez la clé primaire de l'image dans la table des utilisateurs. Si vous souhaitez ajouter d'autres champs ou apporter des modifications à l'avenir, ce sera plus facile - c'est également une bonne pratique.

Si vous êtes préoccupé par le référencement, par exemple, stockez le nom de fichier d'origine de l'image dans un autre champ lorsque vous téléchargez, vous pouvez ensuite l'utiliser dans votre sortie (comme dans la balise alt).

17
Joseph Earl

Remettre en question la sagesse conventionnelle!

Bien sûr, cela dépend du contexte, mais j'ai une très grande application avec des milliers d'images et de documents stockés sous forme de BLOB dans une base de données MySQL (taille moyenne = 2 Mo) et l'application fonctionne correctement sur un serveur de 256 Mo de mémoire. Le secret est une structure de base de données correcte. Conservez toujours deux tables distinctes, l’une contenant les informations de base sur le fichier, l’autre devant contenir uniquement le blob et une clé primaire permettant d’y accéder. Toutes les requêtes de base seront exécutées sur la table de détails, et l’autre table n’est accessible que lorsque le fichier est réellement nécessaire, et l’accès s’effectue à l’aide d’une clé indexée, ce qui garantit des performances extrêmement bonnes. 

Les avantages de stocker des fichiers dans la base de données sont multiples:

  1. Des systèmes de sauvegarde beaucoup plus simples sont nécessaires, car vous n'avez pas besoin de sauvegarder le système de fichiers.
  2. Le contrôle de la sécurité des fichiers est beaucoup plus facile, car vous pouvez valider avant de publier le fichier binaire (oui, vous pouvez stocker le fichier dans un répertoire non public, faire lire un script et régurgiter le fichier, mais les performances ne seront pas beaucoup plus rapides. 
  3. (Similaire au n ° 1) Il sépare proprement le "contenu utilisateur" et le "contenu système", facilitant les migrations et le clonage.
  4. Plus facile à gérer les fichiers, suivre/stocker les modifications de version, etc., car vous avez besoin de moins de modifications de script pour ajouter des contrôles de version.

Si les performances sont un gros problème et que la sécurité et les sauvegardes ne le sont pas (ou si vous avez un bon système de sauvegarde), vous pouvez le stocker dans le système de fichiers, mais même dans ce cas, je stocke souvent des fichiers (dans le cas des images) dans la base de données. et créer un script de mise en cache qui écrit l'image dans un dossier de cache après la première utilisation (oui, cela utilise plus d'espace disque, mais ce n'est jamais un facteur limitant).

Quoi qu'il en soit, bien sûr, FS fonctionne dans de nombreux cas, mais je trouve personnellement que la gestion des bases de données est beaucoup plus simple et flexible, et que si les choses sont bien écrites, les pénalités de performance sont extrêmement faibles.

16
Ben D

Nous avons créé une boutique qui stockait des images dans la base de données. Cela a très bien fonctionné pendant le développement, mais une fois que nous l'avons testé sur les serveurs de production, le temps de chargement des pages était beaucoup trop long, ce qui a ajouté une charge inutile aux serveurs de base de données. 

Bien qu'il semble intéressant de stocker des fichiers binaires dans la base de données, leur extraction et leur manipulation ajoutent une complexité supplémentaire qui peut être évitée en conservant simplement des fichiers sur le système de fichiers et en stockant des chemins/métadonnées dans la base de données.

C'est l'un de ces débats éternels, avec d'excellents arguments des deux côtés, mais pour mon argent, je garderais les images à l'écart de la DB.

10
Neil Aitken

J'ai récemment vu la liste de cette astuce: http://www.ajaxline.com/32-tips-to-speed-up-your-mysql-queries

Conseil 17: Pour votre application Web, les images et autres actifs binaires doivent normalement être stockés sous forme de fichiers. Autrement dit, stockez uniquement une référence au fichier plutôt que le fichier lui-même dans la base de données.

Il suffit donc de sauvegarder le chemin du fichier dans l'image :)

9
AntonioCS

J'ai implémenté les deux solutions (système de fichiers et images persistantes dans la base de données) dans des projets précédents. À mon avis, vous devriez stocker des images dans votre base de données. Voici pourquoi:

  1. Le stockage du système de fichiers est plus compliqué lorsque vos serveurs d'applications sont en cluster. Vous devez avoir un stockage partagé. Même si votre environnement actuel n'est pas en cluster, cela rend plus difficile la montée en puissance lorsque vous en avez besoin.
  2. Vous devriez quand même utiliser un CDN pour votre contenu statique et configurer votre application en tant qu'origine. Cela signifie que votre application ne sera touchée qu'une fois pour une image donnée, puis qu'elle sera mise en cache sur le CDN. CloudFront est très peu coûteux et simple à installer. Il n'y a aucune raison de ne pas l'utiliser. Enregistrez votre bande passante pour votre contenu dynamique.
  3. Il est beaucoup plus rapide (et donc moins coûteux) de développer des images persistantes dans une base de données.
  4. Vous obtenez une intégrité référentielle avec les images persistantes dans la base de données. Si vous stockez des images sur le système de fichiers, vous aurez inévitablement des fichiers orphelins sans enregistrement de base de données correspondant, ou des enregistrements de base de données avec des liens de fichier rompus. Cela arrivera ... c'est juste une question de temps. Vous devrez écrire quelque chose pour les nettoyer.

Quoi qu'il en soit, mes deux cents.

6
Dustin
  1. Quel est le type de données blob de toute façon, sinon pour stocker des fichiers?
  2. Si votre application nécessite une autorisation avant d'accéder aux fichiers, les modifications sont les suivantes: vous stockez les fichiers en dehors de DOCUMENT_ROOT (ils ne peuvent donc pas être consultés directement; et éventuellement b) envoyez le contenu intégral des fichiers via l'application. (bien sûr, vous faites peut-être une sorte de chose nominative pour un nom de fichier haché mais accessible au public). La surcharge de mémoire est donc là, et vous pourriez aussi bien récupérer les données de la base de données.
  3. Si vous devez stocker des fichiers dans un système de fichiers, procédez comme indiqué par Andreas ci-dessus et attribuez-leur un nom en utilisant quelque chose que vous connaissez déjà (c'est-à-dire la clé primaire de la table correspondante).
4
Sam Wilson

Je pense que la plupart des moteurs de base de données sont déjà tellement avancés que le stockage de BLOB de données ne présente aucun inconvénient (base de données gonflée, etc.). L'un des avantages est que vous n'avez pas de lien cassé lorsque l'image est déjà dans la base de données. Cela étant dit, je l’ai toujours fait pour que je stocke le fichier sur disque et que je donne l’URI à la base de données. Cela dépend de l'utilisation. Il peut être plus facile de gérer img-in-db si la page est très dynamique et change souvent - pas d’espace de nom - problèmes. Je dois dire que cela finit par ce que vous préférez.

2
Jens Jansson

Je vous suggère de ne pas stocker l'image dans votre base de données. Au lieu de cela puisque chaque utilisateur aura un identifiant unique associé à son profil dans la base de données, utilisez cet identifiant pour stocker l'image physiquement sur le serveur. 

par exemple. Si un utilisateur a l'identifiant 23, vous pouvez enregistrer une image sur www.votrenom.com/users/profile_images/23.jpg. Ensuite, pour afficher, vous pouvez vérifier si l'image existe et l'afficher en conséquence, sinon afficher votre icône générique.

2
Alec Smart

Comme l'ont suggéré les autres:

  • Stocker les images dans le système de fichiers
  • Ne vous embêtez pas pour stocker le nom de fichier, utilisez simplement l'ID utilisateur (ou tout autre élément que "vous connaissez déjà")
  • Placez des données statiques sur un serveur différent (même si vous utilisez simplement "static.votredomaine.com" comme alias de votre serveur normal)

Pourquoi ?

Plus votre base de données sera volumineuse, plus elle ralentira. Le stockage de votre image dans la base de données augmentera la taille de votre base de données. Le stockage du nom de fichier augmentera la taille de votre base de données.

Mettre des données statiques sur un autre serveur (alias):

  • Facilite la mise à l'échelle
  • La plupart des navigateurs n'enverront pas plus de deux requêtes au même serveur. En plaçant des données statiques sur un "deuxième" serveur, vous accélérez le chargement.
2
Andreas

Après des recherches pendant des jours, j'ai créé un système stockant des images et des fichiers binaires sur la base de données. 

C'était juste génial. J'ai maintenant un contrôle à 100% sur les fichiers, tels que le contrôle d'accès, le dimensionnement des images (je ne redimensionne pas les images de manière dynamique, bien sûr), les statistiques, la sauvegarde et la maintenance.

Dans mes tests de vitesse, le système est maintenant 10 fois plus lent. Cependant, il n'est toujours pas en production et je vais implémenter le cache système et d'autres optimisations.

Vérifiez cet exemple réel, toujours en développement, sur un hôte SHARED, à l'aide d'un MVC: http://www.gt8.com.br/salaodocalcado/calcados/meia-pata/

Dans cet exemple, si un utilisateur est connecté, il peut voir différentes images. Toutes les images de produits et autres fichiers binaires se trouvent dans la base de données, non mis en cache, pas dans FS.

J'ai fait des tests sur un serveur dédié et les résultats ont été au-delà des attentes.

Donc, à mon avis, bien que cela nécessite un effort important, le stockage d’images dans la BD en vaut la peine et les avantages valent bien plus que les inconvénients.

1
user2377782

Dans mon cas, je stocke les fichiers dans système de fichiers . Dans mon dossier Images, je crée un nouveau dossier pour chaque élément nommé en fonction de son identifiant (ligne de la base de données). Et nommez les images dans un ordre commençant à 0. Donc, si j’ai une table nommée Items comme ceci:

       Items      
|-----|------|-----|
| ID  | Name | Date|
|-----|------|-----|
| 29  | Test1| 2014|
|-----|------|-----|
| 30  | Test2| 2015|
|-----|------|-----|
| 31  | Test3| 2016|
|-----|------|-----|

mon répertoire d'images ressemble à quelque chose comme: 

images/
      29/
      30/
      31/


images/29/0.png
images/29/1.jpeg
images/29/2.gif

etc.

0
Elnoor

Comme tout le monde vous l'a dit, ne stockez jamais d'images dans une base de données. Un système de fichiers est utilisé pour stocker des fichiers -> les images sont des fichiers -> stockez-les dans le système de fichiers :-)

0
Lucacri

Ce sont les avantages des deux solutions

En BLOBS:

1) les avantages: la facilité de gestion des grappes puisque vous n’aurez pas à gérer des problèmes complexes tels que la synchronisation de fichiers entre serveurs

2) Les sauvegardes de la base de données seront également exhaustives

Dans les fichiers

1) Mise en cache native manuelle (et c'est le point manquant des commentaires précédents, avec une actualisation et des en-têtes qu'il n'est pas nécessaire de remodeler dans la base de données (les bases ne gèrent pas l'heure de la dernière modification par défaut)

2) Facilité de redimensionnement plus tard

3) Facilité de modération (il suffit de parcourir vos dossiers pour vérifier si tout est correct)

Pour toutes ces raisons et comme les deux pros des bases de données sont plus faciles à répliquer sur un système de fichiers, je recommande fortement les fichiers!

0
Irem

Je viens de tester mon img comme blob, donc. Cette solution fonctionne plus lentement que les images sur le serveur en tant que fichier. Le temps de chargement devrait être le même avec les images de la base de données ou du http, mais ce n’est Pourquoi? Certes, lorsque les images sont des fichiers sur le serveur, le navigateur peut les mettre en cache et les charger une seule fois. Lorsque l’image passe d’une base de données, chaque fois est chargée à nouveau. C'est mon avis. Peut-être que je me trompe sur la mise en cache du navigateur, mais que je travaille plus lentement (blob). Sry mon anglais, peu importe; P

0
Dudeist