PHP para almacenar imágenes en MySQL o no?

He creado una pequeña aplicación web en PHP donde los usuarios primero deben iniciar sesión. Una vez que han iniciado sesión, bash mostrar una pequeña miniatura como parte de su “perfil”.

Tendré que asegurarme de que la imagen esté debajo de un tamaño particular para ahorrar espacio, o asegurarme de que sea una resolución particular, o ambas cosas, o incluso quizás usar algo como la magia de la imagen para reducirla.
No estoy seguro de cuál es el mejor enfoque para eso, todas las ideas son bienvenidas.

Además, he estado tratando de determinar si es mejor almacenar la imagen en la tabla de users de MySQL como un blob, o tal vez una tabla de images separada con un id único, y simplemente almacenar el id. De imagen apropiado en la tabla de users . o simplemente guarde el archivo cargado en el servidor (también a través de una página de carga) y guarde el archivo como el theUsersUniqueUsername.jpg . ¿Mejor opción?

Encontré un tutorial sobre cómo guardar imágenes en mysql aquí: http://www.phpriot.com/articles/images-in-mysql

Solo soy un progtwigdor aficionado, y nunca he hecho algo así antes, así que los ejemplos y / o muchos detalles son muy apreciados.

Siempre depende del contexto, pero generalmente /content/user/{user_id}.jpg una imagen de usuario en el sistema de archivos en una carpeta llamada /content/user/{user_id}.jpg y trato de molestar a la base de datos lo menos posible.

Yo recomendaría almacenar la imagen como un archivo y luego tener el URI del archivo en la base de datos. Si almacena todas las imágenes en la base de datos, es posible que tenga problemas para escalar en una fecha posterior.

Mira esta respuesta también:

El consejo de Microsoft para SQL Server solía ser, para velocidad y tamaño, almacenar imágenes en el sistema de archivos, con enlaces en la base de datos. Creo que han suavizado un poco sus preferencias, pero todavía considero que es una mejor idea, sin duda para el tamaño, ya que no ocupará espacio en la base de datos.

La sobrecarga usando BLOB es mucho menos de lo que la mayoría de la gente quiere que creas, especialmente si lo configuras bien. Si usa un servidor separado simplemente ejecutando el DB para almacenar archivos binarios, entonces de hecho no puede usar ningún sistema de archivos y evitar cualquier sobrecarga del sistema de archivos

Dicho de la manera más fácil / mejor a menos que tengas un par de servidores para ti mismo es almacenarlos en el sistema de archivos

  • No almacene la URL absoluta del archivo en su base de datos, solo la parte única (y posiblemente una carpeta o dos), por ejemplo, 2009/uniqueImageName.jpg o simplemente uniqueImageName.jpg . Luego, en sus páginas solo agregue el host y otras carpetas en el frente, de esa manera tendrá cierta flexibilidad para mover sus imágenes: todo lo que necesitará cambiar es una línea o dos en su página de PHP / ASP.NET.

  • No es necesario almacenar fuera de la raíz del documento para la seguridad: un archivo .htaccess con DENY FROM ALL funcionará igual y brindará más flexibilidad

  • No hay necesidad de ‘derivar’ imágenes para mayor seguridad, solo tiene una página getImage.php o algo así, y luego, en lugar de insertar la URL real en el src de la image , use algo como getImage.php?file=uniqueImageName.jpg . Luego, el archivo getImage.php puede verificar si el usuario está autorizado y tomar la imagen (o no).

  • Use un nombre que garantice ser único (preferiblemente un entero, es decir, clave principal) al almacenar, algunos sistemas de archivos (es decir, Windows) no distinguen entre mayúsculas y minúsculas, por lo que JoeBloggs.jpg y joebloggs.jpg son únicos para la base de datos, pero no para el sistema de archivos por lo que uno sobrescribirá otro.

  • Use una tabla separada para las imágenes y almacene la clave principal de la imagen en la tabla de usuarios. Si alguna vez quiere agregar más campos o realizar cambios en el futuro, será más fácil, también es una buena práctica.

Si le preocupa el SEO y cosas por el estilo, guarde el nombre del archivo original de la imagen en otro campo cuando esté cargando, puede usarlo en su salida (como en la etiqueta alt ).

¡Desafiando la sabiduría convencional!

Por supuesto depende del contexto, pero tengo una aplicación muy grande con miles de imágenes y documentos almacenados como BLOBS en una base de datos MySQL (tamaño promedio = 2MB) y la aplicación funciona bien en un servidor con 256MB de memoria. El secreto es la estructura correcta de la base de datos. Mantenga siempre dos tablas separadas, una de las cuales almacena la información básica sobre el archivo, y la otra tabla solo debe contener la nota más una clave principal para acceder a ella. Todas las consultas básicas se ejecutarán en la tabla de detalles, y la otra tabla solo tendrá acceso cuando el archivo sea realmente necesario, y se accede mediante una clave indexada, por lo que el rendimiento es extremadamente bueno.

Las ventajas de almacenar archivos en la base de datos son múltiples:

  1. Se requieren sistemas de copia de seguridad mucho más fáciles, ya que no es necesario realizar una copia de seguridad del sistema de archivos
  2. Controlar la seguridad de archivos es mucho más fácil ya que se puede validar antes de liberar el archivo binario (sí, puede almacenar el archivo en un directorio no público y tener un script leído y regurgitar el archivo, pero el rendimiento no será notablemente más rápido).
  3. (Similar a # 1) Limpia separadamente el “contenido del usuario” y el “contenido del sistema”, facilitando las migraciones y la clonación.
  4. Más fácil de administrar archivos, rastrear / almacenar cambios de versión, etc., ya que necesita menos modificaciones de guiones para agregar controles de versión.

Si el rendimiento es un gran problema y la seguridad y las copias de seguridad no lo son (o si tiene un buen sistema de respaldo fs), puede almacenarlo en el FS, pero incluso entonces a menudo almaceno archivos (en el caso de las imágenes) en el DB y la creación de un script de almacenamiento en caché que escribe la imagen en una carpeta de caché después de la primera vez que se usó (sí, esto usa más espacio en HD, pero eso casi nunca es un factor limitante).

De todos modos, obviamente FS funciona bien en muchos casos, pero personalmente encuentro que la administración de DB es mucho más fácil y más flexible, y si se escribe bien, las penalizaciones de rendimiento son extremadamente pequeñas.

Creamos una tienda que almacenó imágenes en la base de datos. Funcionó de maravilla durante el desarrollo, pero una vez que lo probamos en los servidores de producción, el tiempo de carga de la página era demasiado alto y agregaba una carga innecesaria a los servidores de la base de datos.

Si bien parece atractivo almacenar archivos binarios en la base de datos, buscarlos y manipularlos agrega una complejidad adicional que se puede evitar simplemente manteniendo los archivos en el sistema de archivos y almacenando rutas / metadatos en la base de datos.

Este es uno de esos debates eternos, con excelentes argumentos en ambos lados, pero por mi dinero mantendría las imágenes lejos del DB.

Hace poco vi la lista de esta sugerencia: http://www.ajaxline.com/32-tips-to-speed-up-your-mysql-queries

Consejo 17: Para su aplicación web, las imágenes y otros activos binarios normalmente deberían almacenarse como archivos. Es decir, almacenar solo una referencia al archivo en lugar del archivo en la base de datos.

Así que solo guarde la ruta del archivo a la imagen 🙂

Implementé ambas soluciones (sistema de archivos e imágenes persistentes en la base de datos) en proyectos anteriores. En mi opinión, debe almacenar imágenes en su base de datos. Este es el por qué:

  1. El almacenamiento del sistema de archivos es más complicado cuando los servidores de aplicaciones están agrupados. Tienes que haber compartido el almacenamiento. Incluso si su entorno actual no está agrupado, esto hace que sea más difícil escalar cuando lo necesite.
  2. Debería utilizar un CDN para su contenido estático de todos modos, y configurar su aplicación como el origen. Esto significa que su aplicación solo se golpeará una vez para una imagen determinada, luego se almacenará en caché en el CDN. CloudFront es muy barato y fácil de configurar … no hay razón para no usarlo. Ahorre su ancho de banda para su contenido dynamic.
  3. Es mucho más rápido (y por lo tanto más económico) desarrollar imágenes persistentes de bases de datos
  4. Obtiene integridad referencial con imágenes persistentes de la base de datos. Si está almacenando imágenes en el sistema de archivos, inevitablemente tendrá archivos huérfanos sin registros de base de datos coincidentes, o tendrá registros de la base de datos con enlaces de archivos rotos. Esto sucederá … es solo cuestión de tiempo. Tendrás que escribir algo para limpiar esto.

De todos modos, mis dos centavos.

  1. ¿Para qué sirve el tipo de datos blob de todos modos, si no es para almacenar archivos?
  2. Si su solicitud implica autorización antes de acceder a los archivos, los cambios consisten en que a) está almacenando los archivos fuera de DOCUMENT_ROOT (por lo que no se puede acceder directamente a ellos, y posiblemente b) enviando todo el contenido de los archivos a través de la aplicación (por supuesto, tal vez estés haciendo algo así como temporalmente-move-to-hashed-but-public-accessible-file). Entonces, la sobrecarga de memoria está ahí de todos modos, y también podría estar recuperando los datos de la base de datos.
  3. Si debe almacenar archivos en un sistema de archivos, haga lo que Andreas sugirió anteriormente y nómbrelos utilizando algo que ya conoce (es decir, la clave principal de la tabla correspondiente).

Creo que la mayoría de los motores de bases de datos ya están tan avanzados que almacenar BLOB de datos no produce inconvenientes (db hinchado, etc.). Una ventaja es que no tiene enlaces rotos cuando la imagen ya está en la base de datos. Dicho esto, siempre he hecho para que almacene el archivo en el disco y le dé el URI a la base de datos. Depende del uso. Puede ser más fácil manejar img-in-db si la página es muy dinámica y cambia con frecuencia, sin problemas de espacio de nombres. Debo decir que termina en lo que prefieres.

Sugeriría que no almacene la imagen en su db. En su lugar, dado que cada usuario tendrá una identificación única asociada con su perfil en la base de datos, use esa identificación para almacenar físicamente la imagen en el servidor.

por ejemplo, si un usuario tiene la ID 23, puede almacenar una imagen en http://www.yourname.com/users/profile_images/23.jpg. Luego, para mostrar, puede verificar si la imagen existe y mostrarla de acuerdo, de lo contrario, muestre su icono genérico.

Como los otros sugirieron:

  • Almacene las imágenes en el sistema de archivos
  • No se moleste en almacenar el nombre del archivo, solo use la identificación del usuario (o cualquier otra cosa que “ya sepa”)
  • Pon datos estáticos en un servidor diferente (incluso si solo usas “static.yourdomain.com” como un alias para tu servidor normal)

Por qué ?

Cuanto más grande sea tu base de datos más lenta será. Almacenar su imagen en la base de datos boostá el tamaño de su base de datos. Almacenar el nombre de archivo boostá el tamaño de su base de datos.

Poniendo datos estáticos en un servidor diferente (alias):

  • Hace que escalar sea mucho más fácil
  • La mayoría de los navegadores no enviarán más de dos solicitudes al mismo servidor, al poner datos estáticos en un “segundo” servidor, usted acelera la carga

Después de investigar durante días, hice un sistema para almacenar imágenes y binarios en la base de datos.

Fue simplemente genial. Ahora tengo el 100% de control sobre los archivos, como el control de acceso, el tamaño de la imagen (no escalo las imágenes dinámicamente, por supuesto), las estadísticas, la copia de seguridad y el mantenimiento.

En mis pruebas de velocidad, el sistema ahora es 10 veces más lento. Sin embargo, todavía no está en producción e implementaré el caché del sistema y otras optimizaciones.

Verifique este ejemplo real, aún en desarrollo, en un host COMPARTIDO, utilizando un MVC: http://www.gt8.com.br/salaodocalcado/calcados/meia-pata/

En este ejemplo, si un usuario está conectado, puede ver imágenes diferentes. Todas las imágenes de productos y otros binarios están en DB, no en caché, no en FS.

Hice algunas pruebas en un servidor dedicado y los resultados fueron mucho más allá de las expectativas.

Entonces, en mi opinión personal, aunque se necesita un gran esfuerzo para lograrlo, el almacenamiento de imágenes en DB vale la pena y los beneficios valen mucho más las desventajas.

Como todos los demás te dijeron, nunca almacenes imágenes en una base de datos. Un sistema de archivos se usa para almacenar archivos -> las imágenes son archivos -> almacenarlas en el sistema de archivos 🙂

Acabo de probar mi img como blob, entonces. Esta solución funciona más lento que las imágenes en el servidor como archivo. El tiempo de carga debe ser el mismo con imágenes de DB o http pero no lo es. ¿Por qué? Estoy seguro de que cuando las imágenes son archivos en el servidor, el navegador puede almacenarlas en la memoria caché y cargarlas una sola vez, por primera vez. Cuando la imagen va de DB, cada vez se carga de nuevo. Esa es mi opinión. Tal vez estoy equivocado sobre el almacenamiento en caché del navegador, pero trabajando más lento (blob). Sry mi inglés, lo que sea, P

Estos son los pros de ambas soluciones

En BLOBS:

1) pros: la facilidad para administrar clusters ya que no tiene que manejar puntos difíciles como sincronizaciones de archivos entre servidores

2) Las copias de seguridad de DB también serán exhaustivas

En archivos

1) Almacenamiento en memoria caché nativo a mano (y ese es el punto que falta de los comentarios anteriores, con actualización y encabezados que no tendrá que rediseñar en DB (DB no está manejando el tiempo de la última modificación por defecto)

2) Facilidad de redimensionamiento más tarde

3) Facilidad de moderación (solo revisa tus carpetas para verificar si todo está correcto)

Por todos estos motivos, y dado que las dos ventajas de las bases de datos son más fáciles de replicar en el sistema de archivos, ¡recomiendo encarecidamente los archivos!

En mi caso, guardo archivos en el sistema de archivos . En mi carpeta de imágenes, creo una nueva carpeta para cada elemento nombrado en función de la identificación del elemento (fila de db). Y nombre las imágenes en un orden que empiece por 0. Entonces, si tengo una tabla llamada Elementos como este:

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

mi directorio de imágenes se parece a algo así como:

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

etc.