php - validar - Almacenamiento eficiente de imágenes subidas por el usuario en el sistema de archivos
mysql imagenes php (3)
Guión
Los usuarios pueden publicar un elemento e incluir hasta 5 imágenes con la publicación, cada imagen que se carga debe ser remuestreada y redimensionada, se crean un total de 4 imágenes adicionales. Lo que significa que si el usuario carga 5 imágenes terminará con 25 imágenes en total para almacenar.
Suposiciones
- Las imágenes se han comprobado correctamente y son archivos de imagen válidos.
- El sistema tiene que escalar (asumamos 1000 publicaciones en primera instancia, por lo tanto, un máximo de 5000 imágenes)
- Se cambia el nombre de cada imagen en relación con el ID auto_incremenet de la entrada de db post e incluye el sufijo relevante, es decir, 12345_1_1.jpg 12345_2_1.jpg, por lo que no hay problemas con los duplicados
- Las imágenes no son de naturaleza sensible, por lo que no hay problemas para tenerlas directamente accesibles (aunque la lista de directorios estaría deshabilitada)
Posibles enfoques
- Dado que los ID son únicos, podríamos simplemente colocarlos en una carpeta (ineficaz después de cierto punto).
- Podría crear una carpeta para cada publicación y colocar todas las imágenes en ella, por lo que ROOT / images / 12345 (nuevamente, terminaría con una multitud de carpetas)
- Podría hacer un almacén de imágenes basado en la fecha, es decir, cada día se crea una nueva carpeta y los días en que las imágenes se almacenan allí.
- Podía almacenar las imágenes según el tipo de tamaño cambiado, es decir, todos los archivos originales se podrían almacenar en una carpeta imágenes / orig todas las miniaturas en imágenes / pulgar (creo que Gumtree utiliza un enfoque como este).
- Podría permitir que X cantidad de archivos se almacenen en una carpeta antes de crear otra.
¿Alguien tiene experiencia en las mejores prácticas / enfoques a la hora de almacenar imágenes de forma escalable?
Nota: creo que alguien mencionará S3. Supongamos que queremos mantener las imágenes localmente por el momento.
Gracias por mirar
Almaceno todas las imágenes en una sola carpeta; la base de datos luego mantiene un registro de los nombres de los archivos;
En primer lugar, recomendaría crear una tabla para las imágenes. Esta es una tabla de una fila / archivo de imagen:
| id | filename | type | storage |
---------------------------------------
| 123 | 123.png | original | store1 |
-
id
auto incremental int o algo igualmente único. -
filename
archivo elfilename
la base de archivos. Esto le permite mover el archivo y simplemente actualizar el código. El nombre del archivo podría ser{file_id}.{extension}
. -
type
es el tipo de imagen:original
,thumbnail
,resized
, lo que sea. También podrían ser las dimensiones:100x100
,x500
,x500
(dondex500
sería de altura ilimitada yx500
ancho ilimitado). Estos son sólo algunos ejemplos. -
storage
sería un identificador de donde está el archivo, esto podría ser un directorio. Digamos que almacena sus imágenes enpost_images
, el nombre de archivo es123.png
y el almacenamiento esstore1
, entonces la ruta seríapost_images/store1/123.png
.
Todavía tengo que intentarlo, pero tengo problemas con las aplicaciones web que almacenan archivos de 10k + en el mismo directorio.
Tenemos un sistema de este tipo en producción pesada con más de 30,000 archivos y más de 20 GB hasta la fecha ...
Column | Type | Modifiers
-------------+-----------------------------+----------------------------------------------------------
File_ID | integer | not null default nextval(''"ACRM"."File_pseq"''::regclass)
CreateDate | timestamp(6) with time zone | not null default now()
FileName | character varying(255) | not null default NULL::character varying
ContentType | character varying(128) | not null default NULL::character varying
Size | integer | not null
Hash | character varying(40) | not null
Indexes:
"File_pkey" PRIMARY KEY, btree ("File_ID")
Los archivos solo se almacenan en un solo directorio con el entero File_ID como el nombre del archivo. Somos más de 30,000 sin problemas. He probado más alto sin problemas.
Esto está utilizando RHEL 5 x86_64 con ext3 como sistema de archivos.
¿Lo haría de esta manera otra vez? No. Déjame compartir un par de pensamientos sobre un rediseño.
La base de datos sigue siendo la "fuente maestra" de información sobre los archivos.
Cada archivo se sha1 () hash y se almacena en una jerarquía de sistema de archivos en función de ese hash: /
/FileData/ab/cd/abcd4548293827394723984723432987.jpg
//FileData/ab/cd/abcd4548293827394723984723432987.jpg
//FileData/ab/cd/abcd4548293827394723984723432987.jpg
//FileData/ab/cd/abcd4548293827394723984723432987.jpg
La base de datos es un poco más inteligente sobre el almacenamiento de metainformación en cada archivo. Sería un sistema de tres mesas:
File
: almacena información como nombre, fecha, ip, propietario y un puntero a un Blob (sha1)
File_Meta
: almacena pares clave / valor en el archivo, dependiendo del tipo de archivo. Esto puede incluir información como Image_Width, etc ...
Blob
: almacena una referencia al sha1 junto con su tamaño.
Este sistema eliminaría la duplicación del contenido del archivo almacenando los datos a los que hace referencia un hash (varios archivos podrían hacer referencia al mismo archivo de datos). Sería muy fácil hacer una copia de seguridad de la base de datos de archivos usando rsync.
Además, se eliminarán las limitaciones de un directorio dado que contiene muchos archivos.
La extensión del archivo se almacenará como parte del hash de archivo único. Por ejemplo, si el hash para un archivo vacío fuera abcd8765
... Un archivo .txt
vacío y un archivo .php
vacío se referirán al mismo hash. Más bien, deben referirse a abcd8765.php
y abcd8765.txt
. ¿Por qué?
Apache, etc. puede configurarse para elegir automáticamente el tipo de contenido y las reglas de almacenamiento en caché según la extensión del archivo. Es importante almacenar los archivos con un nombre válido y la extensión que refleja el contenido del archivo.
Verá, este sistema realmente podría mejorar el rendimiento al delegar la entrega de archivos a través de nginx. Ver http://wiki.nginx.org/XSendfile .
Espero que esto ayude de alguna manera. Cuídate.