¿Cuál es el mejor lugar para almacenar imágenes cargadas, bases de datos SQL o sistemas de archivos de disco?

Estoy escribiendo una aplicación que permite a los usuarios subir imágenes al servidor. Espero alrededor de 20 imágenes por día, todo JPEG y probablemente no editado / redimensionado. (Esta es otra pregunta, cómo cambiar el tamaño de las imágenes en el lado del servidor antes de almacenar. Tal vez alguien pueda dejar caer un recurso de .NET para eso en el comentario o menos). Me pregunto ahora cuál es el mejor lugar para almacenar imágenes cargadas.

  • Almacene las imágenes como un archivo en el sistema de archivos y cree un registro en una tabla con la ruta exacta a esa imagen.

  • O bien, almacene la imagen en una tabla utilizando un tipo de datos “imagen” o “datos binarios” del servidor de la base de datos.

Veo ventajas y desventajas en ambos. Me gusta a) porque puedo reubicar fácilmente los archivos y solo tengo que cambiar la entrada de la tabla. Por otro lado, no me gusta almacenar datos comerciales en el servidor web y realmente no quiero conectar el servidor web a ningún otro origen de datos que contenga datos comerciales (por razones de seguridad) Me gusta b) porque toda la información es en un lugar y de fácil acceso mediante una consulta. Por otro lado, la base de datos se hará muy grande muy pronto. Subcontratar esos datos podría ser más difícil.

Generalmente almaceno archivos en el sistema de archivos, ya que eso es lo que está ahí, aunque hay excepciones. Para los archivos, el sistema de archivos es la solución más flexible y de rendimiento (generalmente).

Existen algunos problemas para almacenar archivos en una base de datos, los archivos generalmente son mucho más grandes que la fila promedio, los conjuntos de resultados que contienen muchos archivos grandes consumirán mucha memoria. Además, si utiliza un motor de almacenamiento que emplea lockings de tabla para escrituras (ISAM, por ejemplo), su tabla de archivos puede bloquearse a menudo dependiendo del tamaño / índice de archivos que está almacenando allí.

Con respecto a la seguridad, generalmente almaceno los archivos en un directorio que está fuera de la raíz del documento (no accesible a través de una solicitud http) y los sirvo a través de un script que primero verifica la autorización adecuada.

El único beneficio para la opción B es tener todos los datos en un sistema, ¡pero es un beneficio falso! Puede argumentar que su código también es una forma de datos y, por lo tanto, también se puede almacenar en la base de datos. ¿Cómo le gustaría?

A menos que tengas un caso único:

  • La lógica de negocios pertenece al código.
  • Los datos estructurados pertenecen a la base de datos (relacional o no relacional).
  • Los datos masivos pertenecen al almacenamiento (sistema de archivos u otro).

Archivos, Código, Datos

No es necesario usar el sistema de archivos para guardar los archivos. En su lugar, puede usar almacenamiento en la nube (como Amazon S3 ) o Infraestructura como servicio (como Uploadcare ):

https://uploadcare.com/upload-api-cloud-storage-and-cdn/

Pero almacenar archivos en la base de datos es una mala idea.

Flickr usa el sistema de archivos, discuten los motivos aquí

Hemos tenido clientes que insisten en la opción B (almacenamiento de la base de datos) unas pocas veces en algunos backends diferentes, y siempre terminamos volviendo a la opción A (almacenamiento del sistema de archivos) eventualmente.

Los grandes BLOB como estos simplemente no han sido manejados lo suficientemente bien incluso por SQL Server 2005, que es el último en el que lo probamos.

Específicamente, vimos problemas graves y creo que tal vez problemas de locking.

Otra nota: si está utilizando el almacenamiento basado en NTFS (servidor de Windows, etc.) puede considerar encontrar la forma de colocar miles y miles de archivos en un directorio. No estoy seguro de por qué, pero a veces el sistema de archivos no se adapta bien a esa situación. Si alguien sabe más acerca de esto, me encantaría escucharlo.

Pero siempre trato de usar subdirectorios para romper un poco las cosas. La fecha de creación a menudo funciona bien para esto:

Imágenes / 2008/12/17 / .jpg

… Esto proporciona un nivel aceptable de separación, y también ayuda un poco durante la depuración. Tanto los clientes de Explorer como los de FTP pueden ahogarse un poco cuando existen directorios realmente enormes.

EDITAR: solo una nota rápida para 2017, en versiones más recientes de SQL Server, hay nuevas opciones para manejar muchos BLOB que se supone que evitan los inconvenientes que discutí.

Recientemente he creado una aplicación PHP / MySQL que almacena archivos PDF / Word en una tabla MySQL (tan grande como 40 MB por archivo hasta el momento).

Pros:

  • Los archivos cargados se replican en el servidor de respaldo junto con todo lo demás, no se necesita una estrategia de respaldo separada (tranquilidad).
  • Configurar el servidor web es un poco más simple porque no necesito tener una carpeta de carga / uploads y decirle a todas mis aplicaciones dónde está.
  • Puedo usar transacciones para ediciones para mejorar la integridad de los datos. No tengo que preocuparme por los archivos huérfanos y perdidos.

Contras:

  • mysqldump ahora lleva mucho tiempo porque hay 500 MB de datos de archivo en una de las tablas.
  • En general, no es muy eficiente en cuanto a memoria / CPU en comparación con el sistema de archivos

Llamaría a mi implementación un éxito, se ocupa de los requisitos de copia de seguridad y simplifica el diseño del proyecto. El rendimiento está bien para las 20-30 personas que usan la aplicación.

Utilizo imágenes cargadas en mi sitio web y definitivamente diría la opción a).

Otra cosa que recomiendo es cambiar inmediatamente el nombre del archivo de lo que el usuario ha llamado la foto a algo más manejable. Por ejemplo, algo con la fecha y la hora para identificar de forma única cada imagen.

También ayuda a quitar el nombre de archivo del usuario de los caracteres extraños para evitar futuras complicaciones.

Definitivamente cambie el tamaño de la imagen, y verifique su formato si puede. Ha habido casos de archivos maliciosos cargados y servidos por hosts involuntarios, por ejemplo, la vulnerabilidad GIFAR le permitió ocultar un applet malicioso de java en un archivo GIF, que luego podría leer las cookies en el contexto actual y enviarlas a otro sitio para un ataque de scripting entre sitios. Cambiar el tamaño de las imágenes generalmente evita esto, ya que afecta el código incrustado. Si bien este ataque se ha solucionado mediante parches de JVM, el simple hecho de servir archivos binarios sin depurarlos lo abre a toda una gama de vulnerabilidades.

Recuerde que la mayoría de los escáneres de virus solo pueden ejecutarse contra el sistema de archivos. Si almacena sus binarios en la base de datos, no podrá ejecutar un escáner fácilmente.

Sé que esta es una publicación anterior. Pero muchos visitantes a esta página no reciben nada relacionado con la pregunta. Especialmente para un novato.

Cómo cargar y almacenar imágenes o archivos en nuestro sitio web:

Para un sitio web estático, tal vez no haya problema, ya que el almacenamiento de archivos para algunos sitios web de alojamiento compartido sigue siendo adecuado. El problema proviene de un sitio web dynamic cuando crece. Más grande en la base de datos se puede manejar, pero más grande en el archivo, como las imágenes se convierte en un problema. Hay dos tipos de imágenes en un sitio web:

  1. Las imágenes provienen del administrador para el blog dynamic. Por lo general, estas imágenes se han optimizado antes de la carga.

  2. Las imágenes de los usuarios en el caso de los usuarios pueden subir imágenes como avatar. O los usuarios pueden crear contenido de blog y poner algunas imágenes del editor de texto. Este tipo de imágenes es difícil de predecir el tamaño. Los usuarios pueden cargar imágenes grandes solo para contenido pequeño cambiando el tamaño del tamaño de la vista pero sin cambiar el tamaño del tamaño de la imagen.

Al ignorar el ítem no. 1 arriba, solución rápida para el ítem no. 2 puede resolverse temporalmente con los siguientes consejos si no tenemos la funcionalidad del optimizador de imagen en nuestro sitio web:

  1. No permita que los usuarios carguen directamente desde el editor de texto redirigiéndolos a la galería de imágenes. En esta página, los usuarios deben cargar el archivo por adelantado antes de que puedan incrustarse en el contenido. Este método se llama Administrador de archivos.

  2. Use una función de recorte de imagen para que los usuarios carguen imágenes. Esto limitará el tamaño de la imagen, incluso los usuarios cargan archivos muy grandes. La imagen final es el resultado de la imagen recortada. Podemos definir el tamaño en el lado del servidor y aceptar solo, por ejemplo, 500 Kb o menos.

Ahora, eso es solo temporal. Para la solución final, la pregunta se repite:

  • ¿Cómo manejar un almacenamiento de imágenes grandes?
  • Cambiar el tamaño o cambiar la extensión.
  • ¿Cómo maneja el sitio web o comercio electrónico grande o mediano el almacenamiento de archivos para sus imágenes?

Qué podemos hacer entonces:

  1. Migrar desde el servidor compartido VPS. ¿No es suficiente? Luego, más alto actualizando a Dedicado.

  2. Crea tu propio servidor para el almacenamiento de archivos. Buscando en Google para hacerlo. Esto no es tan difícil como crees. Algunas personas lo hacen por su sitio web.

  3. La manera más fácil es usar el servicio de almacenamiento de archivos CDN.

De acuerdo, 1 y 2 son un poco caros. Pero no, creo que es la mejor solución.

Algunos servicios de CDN le permiten almacenar tantos archivos web como desee.

Pregunta, “¿cómo subir un archivo a CDN desde nuestro sitio web?”

No se preocupe, una vez que se registre, generalmente gratis, obtendrá una guía sobre cómo cargar un archivo y obtener su enlace desde / hacia su sitio web. Obtendrás una API y más. Es fácil.

Algunos proveedores nos brindan un servicio gratuito durante 14 días con almacenamiento y ancho de banda limitados. Pero eso estará bien para el punto de partida. El único problema es porque “la gente nunca lo intenta”.

Espero que ayude a los novatos.

La mayoría de las implementaciones son la opción A.

Con la opción B, abres una gran lata de whoop4ss cuando recuperas esos bits de la base de datos en algo que puede mostrarse en un navegador … Además, si el db está inactivo, las imágenes no están disponibles.

No creo que ese espacio sea demasiado problemático … Las unidades Terabyte cuestan unos cientos de dólares ahora.

Estamos implementando con la opción A porque no tenemos el tiempo ni los recursos para hacer la opción B.

Hay una especie de enfoque híbrido en SQL Server 2008 llamado el tipo de datos filestream del que se habló en RunAs Radio # 74 , que es algo así como lo mejor de ambos mundos. La mayoría de las personas no tienen el otión 2008, pero si lo haces, esta opción se ve muy bien

Usamos A. Lo pondría en una unidad compartida (a menos que no planee ejecutar más de un servidor).

Si llega el momento en que esto no se ampliará para usted, entonces puede investigar los mecanismos de almacenamiento en caché.

Definitivamente, de manera positiva, la opción A. Otros han mencionado que las bases de datos generalmente no funcionan bien con los BLOB, ya sea que estén diseñados para hacerlo o no. Los sistemas de archivos, por otro lado, viven para esto. Tiene la opción de utilizar la creación de bandas RAID, difundir imágenes entre varias unidades, incluso difundirlas entre servidores geográficamente dispares.

Otra ventaja es que las copias de seguridad / replicación de la base de datos serían monstruosas.

Para el cambio de tamaño automático, pruebe imagemgick … se usa para muchos sistemas de administración de contenido / fotografía de código abierto … y creo que hay algunas extensiones .net para él.

Opción A.

Una vez que cargue la imagen, puede verificar el formato y cambiar su tamaño antes de guardar. Hay una serie de muestras de código .Net para cambiar el tamaño de las imágenes en http://www.codeproject.com . Por ejemplo: http://www.codeproject.com/KB/cs/Photo_Resize.aspx

Por razones de seguridad, también es una buena práctica evitar los problemas causados ​​por el “Content Sniffing” de IE, que puede permitir a los atacantes cargar JavaScript dentro de los archivos de imágenes, lo que podría ejecutarse en el contexto de su sitio. Así que es posible que desee transformar las imágenes (recortarlas / redimensionarlas) de alguna manera antes de almacenarlas para evitar este tipo de ataque. Esta respuesta tiene algunas otras ideas.

Bueno, tengo un proyecto similar donde los usuarios cargan archivos en el servidor. Bajo mi punto de vista, la opción a) es la mejor solución debido a que es más flexible. Lo que debe hacer es almacenar imágenes en una carpeta protegida clasificada por subdirectorios. El administrador debe configurar el directorio principal ya que el contenido no debe ejecutar scripts (muy importantes) y (leer, escribir) protegidos para no ser accesibles en la solicitud http.

Espero que esto te ayude.

Esto es básicamente lo que hago.

  1. Almacene una imagen cargada en el directorio o memoria temporal.
  2. Procese esa imagen antes de almacenarla permanentemente. 2.1. Correcciones de color 2.2. Comprimir 2.3. Crea varias copias según las dimensiones de la imagen 2.4. Cambiar el nombre con sufijos .xl, .lg, .md, .sm, etc.
  3. Empaque todos los archivos de imagen procesados ​​(de un único archivo) dentro de una carpeta con nombre de carpeta como id que se almacenará en la base de datos para cualquier fila / documento junto con image file name (o puede ser un nombre aleatorio como nombre de imagen).
  4. Cree la carpeta de path aaaa / mm / d si no existe. Por ejemplo, 2016/08/21. Recuerde esa ruta y almacene en la base de datos para el mismo documento y fila.
  5. Mueva la carpeta de id imagen a la carpeta de path . (La carpeta de ruta puede estar ubicada en la carpeta / var / web-content).
  6. Vaciar el búfer de memoria o eliminar el archivo temporal.

Cuando necesite acceder a cualquier imagen mencionada en un documento, tiene la ruta y el id. De la carpeta que contiene imágenes. Por ejemplo /var/web-content/{{path}}/{{id}}/image-file-name.sm.jpg

De esta forma, si tiene que eliminar todos los archivos de imágenes procesadas, simplemente elimine la carpeta y su contenido recursivamente.

Si son archivos pequeños que no necesitarán ser editados, la opción B no es una mala opción. Prefiero esto a escribir lógica para almacenar archivos y lidiar con problemas de estructura de directorios. Tener muchos archivos en un directorio es malo. emkay?

Si los archivos son grandes o requieren una edición constante, especialmente desde progtwigs como la oficina, entonces la opción A es su mejor opción.

Para la mayoría de los casos, es una cuestión de preferencia, pero si vas a la opción A, simplemente haz que los directorios no tengan demasiados archivos. Si elige la opción B, haga que la tabla con los datos BLOBed esté en su propia base de datos y / o grupo de archivos. Esto ayudará con el mantenimiento, especialmente las copias de seguridad / restauraciones. Es probable que sus datos regulares sean bastante pequeños, mientras que los datos de su imagen serán enormes a lo largo del tiempo.

Depende de sus requisitos, especialmente el volumen, los usuarios y la frecuencia de búsqueda. Pero, para oficinas pequeñas o medianas, la mejor opción es usar una aplicación como Apple Photos o Adobe Lighroom. Están especializados para almacenar, catalogar, indexar y organizar este tipo de recurso. Pero, para organizaciones grandes, con requisitos sólidos de almacenamiento y una gran cantidad de usuarios, se recomienda crear una plataforma de Gestión de Contenidos con una Gestión de Activos Digitales, como Nuxeo o Alfresco; Ambas ofrecen muy buenos recursos, manejan grandes volúmenes de datos con métodos simplificados para recuperarlos. Y, muy importante: hay una opción gratuita (de código abierto) para ambas plataformas.