2009-05-23 3 views
10

Estoy recibiendo miles de imágenes cargadas por miles de usuarios en mi servidor Linux, alojado por 1and1.com (creo que usan CentOS, pero no estoy seguro de la versión). Esta es una pregunta independiente del idioma, sin embargo, para su referencia, estoy usando PHP.Miles de imágenes, ¿cómo debo organizar la estructura del directorio? (linux)

Mi primer pensamiento fue simplemente volcarlos todos en el mismo directorio, sin embargo, recuerdo que hace un tiempo, había un límite de cuántos archivos o directorios podían soltarse en un directorio.

Mi segundo pensamiento fue dividir los archivos dentro de directorios basados ​​en la dirección de correo electrónico del usuario (ya que es lo que estoy usando para el nombre de usuario de todos modos) pero no quiero correr al límite para directorios en un directorio ....

de todos modos, para las imágenes de [email protected], que iba a hacer esto:

/images/domain.com/user/images... 

Es esto más inteligente que hacer, lo que si miles de usuarios tienen diga 'gmail' quizá Incluso podría ir más profundo, como este

/images/domain.com/[first letter of user name]/user/images... 

así que para [email protected] sería ...

/images/domain.com/m/mike/images... 

¿Es un mal enfoque? ¿Qué están haciendo todos los demás? Yo no quiero tener problemas con demasiados directorios ...


relacionadas:

+0

y estoy bastante seguro de que había otra pregunta (más estrechamente) relacionada, pero no la encontré ... – dmckee

+0

Ciertamente hay un par de preguntas de tipo "sistema de archivos o base de datos". – dmckee

Respuesta

27

yo haría lo siguiente:.

  1. Tome un hash MD5 de cada imagen, ya que viene en
  2. escribir que hash MD5 en la base de datos donde estás haciendo un seguimiento de estas cosas.
  3. Guárdelos en una estructura de directorio donde utilice los primeros dos bytes de la cadena hexadecimal MD5 como el nombre del directorio. Entonces, si el hash es 'abcdef1234567890' lo almacenarías como 'a/b/abcdef1234567890'.

El uso de un hash también le permite combinar la misma imagen cargada varias veces.

+2

Un par de comentarios: 1) sal de su hash con un valor conocido. 2) "Balance de árbol" el hash en la estructura de la carpeta.Así que tome el primero (digamos) cinco caracteres del hash y conviértalo en una carpeta, luego en los siguientes cinco, etc. De modo que nunca tendrá más de 100.000 carpetas en una carpeta determinada. Use todo el hash en la estructura de carpetas de esta manera. –

3

Lo que utilicé para otro requisito pero que puede satisfacer sus necesidades es usar una convención simple.

Incremente en 1 y obtenga la longitud del nuevo número, y luego prefija este número.

Por ejemplo:

Suponga 'a' es un var que se establece con el último ID.

a = 564; 
++a; 
prefix = length(a); 
id = prefix + a; // 3565 

A continuación, puede utilizar una marca de tiempo para el directorio, el uso de esta convención:

20092305 (yyyymmdd) 

A continuación, puede explotar su camino como esto:

2009/23/05/3565.jpg 

(o más)

Es interesante porque puede guardar un orden de clasificación por fecha y por número al mismo tiempo (a veces útil) Y todavía se puede descomponer su camino en más directorios

4

de ampliar el enfoque de Joe Beda:

  • base de datos de la base de datos
  • base de datos

si se preocupan por la agrupación o la búsqueda de archivos de usuario, nombre de archivo original, fecha de carga, foto -take-on date (EXIF), etc., almacene estos metadatos en una base de datos y use las consultas apropiadas para seleccionar los archivos apropiados.

Usar la base de datos primaria clave — si un hash de archivo, o un número autoincremental — para localizar archivos entre un conjunto fijo de directorios (otra alternativa es utilizar un directorio fijo indica el número máximo de archivos N por, y cuando surte ir a la siguiente, por ejemplo, k la foto debe almacenarse en {somepath}/aaaaaa/bbbb.jpg donde aaaaaa = piso (k/N), formateada como decimal o hexadecimal, y bbbb = mod (k, N), formateada como decimal o hexagonal . Si esa es una jerarquía demasiado plana para usted, use algo como {somepath}/aa/bb/cc/dd/ee.jpg)

No exponga la estructura del directorio directamente a sus usuarios. Si utilizan navegadores web para acceder a su servidor a través de HTTP, proporcióneles una url como www.myserver.com/images/{primary key} y codifique el tipo de archivo adecuado en el encabezado Content-Type.

+0

todas las imágenes estarán debajo de la raíz de la carpeta web, por lo que no pueden acceder a ellas sin utilizar nuestra función para recuperarlas. – MichaelICE

+0

todavía, si hace la estructura a la que acceden, junto con la estructura en la que los almacena, entonces está atascado sin cambiar la URL. Si se desacopla, puede cambiar la estructura de almacenamiento más tarde si es necesario. –

3

Aquí hay dos funciones que escribí hace un tiempo exactamente para esta situación. Han estado en uso durante más de un año en un sitio con miles de miembros, cada uno de los cuales tiene muchos archivos.

En esencia, la idea es usar los últimos dígitos de la ID de base de datos única de cada miembro para calcular una estructura de directorio, con un directorio único para todos. El uso de los últimos dígitos, en lugar del primero, garantiza una distribución más uniforme de los directorios.Un directorio separado para cada miembro significa que las tareas de mantenimiento son mucho más simples, además de que puede ver dónde está el material de las personas (como en forma visual).

// checks for member-directories & creates them if required 
function member_dirs($user_id) { 

    $user_id = sanitize_var($user_id); 

    $last_pos = strlen($user_id); 
    $dir_1_pos = $last_pos - 1; 
    $dir_2_pos = $last_pos - 2; 
    $dir_3_pos = $last_pos - 3; 

    $dir_1 = substr($user_id, $dir_1_pos, $last_pos); 
    $dir_2 = substr($user_id, $dir_2_pos, $last_pos); 
    $dir_3 = substr($user_id, $dir_3_pos, $last_pos); 

    $user_dir[0] = $GLOBALS['site_path'] . "files/members/" . $dir_1 . "/"; 
    $user_dir[1] = $user_dir[0] . $dir_2 . "/"; 
    $user_dir[2] = $user_dir[1] . $dir_3 . "/"; 
    $user_dir[3] = $user_dir[2] . $user_id . "/"; 
    $user_dir[4] = $user_dir[3] . "sml/"; 
    $user_dir[5] = $user_dir[3] . "lrg/"; 

    foreach ($user_dir as $this_dir) { 
     if (!is_dir($this_dir)) { // directory doesn't exist 
      if (!mkdir($this_dir, 0777)) { // attempt to make it with read, write, execute permissions 
       return false; // bug out if it can't be created 
      } 
     } 
    } 

    // if we've got to here all directories exist or have been created so all good 
    return true; 

} 

// accompanying function to above 
function make_path_from_id($user_id) { 

    $user_id = sanitize_var($user_id); 

    $last_pos = strlen($user_id); 
    $dir_1_pos = $last_pos - 1; 
    $dir_2_pos = $last_pos - 2; 
    $dir_3_pos = $last_pos - 3; 

    $dir_1 = substr($user_id, $dir_1_pos, $last_pos); 
    $dir_2 = substr($user_id, $dir_2_pos, $last_pos); 
    $dir_3 = substr($user_id, $dir_3_pos, $last_pos); 

    $user_path = "files/members/" . $dir_1 . "/" . $dir_2 . "/" . $dir_3 . "/" . $user_id . "/"; 
    return $user_path; 

} 

sanitize_var() es una función de soporte para el fregado de entrada & asegurar que es numérico, $ GLOBALS [ 'SITE_PATH'] es la ruta absoluta para el servidor. Con suerte, se explicarán por sí mismos de lo contrario.

2

La respuesta de Joe Beda es casi perfecta, pero tenga en cuenta que el MD5 ha demostrado ser colisible en iirc 2 horas en una computadora portátil?

Dicho esto, si realmente va a utilizar el hash MD5 del archivo de la manera descrita, su servicio será vulnerable a los ataques. ¿Cómo se verá el ataque?

  1. Un hacker no le gusta una foto en particular
  2. Él asegura que este es MD5 llanura que está utilizando (MD5 de la imagen + secret_string puede asustar a sacarlo)
  3. Se utiliza un método mágico de chocar una imagen de (use su imaginación aquí) hash con la foto que no le gusta
  4. se carga la foto como si haría normalmente
  5. Su servicio sobrescribe el viejo por uno nuevo y muestra tanto

Alguien dice: no lo sobreescribamos entonces. Entonces, si es posible predecir que alguien va a subir algo (es decir, que se cargue una imagen popular en la Web), primero es posible tomar el "lugar de hash". El usuario estaría feliz al subir una imagen de un gatito. Descubriría que en realidad aparece como (usa Tu imaginación aquí). Digo: ¿usar SHA1, ya que se ha demostrado que se puede hackear en iirc 127 años por un clúster de 10.000 computadoras?

+0

estás hablando de un ataque de preimagen, que aún no ha sido exitoso contra MD5, solo ataques de colisión http://www.vpnc.org/hash.html –

+1

http://en.wikipedia.org/wiki/MD5 : "El 1 de marzo de 2005, Arjen Lenstra, Xiaoyun Wang y Benne de Weger demostraron la construcción de dos certificados X.509 con diferentes claves públicas y el mismo hash MD5, una colisión práctica demostrable". (...) –

0

Puede llegar tarde al juego en esto. Pero una solución (si se ajusta a su caso de uso) podría ser el hashing de nombre de archivo. Es una forma de crear una ruta de archivo fácilmente reproducible utilizando el nombre del archivo y al mismo tiempo crear una estructura de directorios bien distribuida. Por ejemplo, puede utilizar los bytes de código hash del nombre de archivo como su trayectoria:

String fileName = "cat.gif"; 
int hash = fileName.hashCode(); 
int mask = 255; 
int firstDir = hash & mask; 
int secondDir = (hash >> 8) & mask; 

Esto daría como resultado el ser ruta:

/172/029/cat.gif 

continuación puede encontrar cat.gif en la estructura de directorios mediante la reproducción de la algoritmo.

Usando HEX como los nombres de directorio sería tan fácil como convertir los int valores:

String path = new StringBuilder(File.separator) 
     .append(String.format("%02x", firstDir)) 
     .append(File.separator) 
     .append(String.format("%02x", secondDir) 
     .toString(); 

El resultado es:

/AC/1D/cat.gif 

escribí un artículo sobre esto hace unos años y recientemente se trasladó a Medio. Tiene algunos detalles más y algunos ejemplos de código: File Name Hashing: Creating a Hashed Directory Structure. ¡Espero que esto ayude!

Cuestiones relacionadas