¿Cuál es la mejor práctica para nombrar imágenes cargadas?

15

Supongamos que tengo un formulario en mi aplicación web donde los usuarios pueden subir una foto de perfil.

Tengo pocos requisitos sobre el tamaño del archivo, las dimensiones, etc., pero cuando el usuario carga la imagen, ¿cómo debo nombrarlos en mi sistema? Supongo que debería ser consistente y también único.

Tal vez un GUID?

a5c627bedc3c44b7ae7c06a44fb3fcf8.jpg

¿Una marca de tiempo?

129899740140465735.jpg

Un hash? Ej: md5

b1a9acaf295cf14ffbc5b6538294562c.jpg

¿Existe una forma estándar o recomendada de hacer esto?

Rowan Freeman
fuente
77
Si su objetivo es almacenar solo una imagen de perfil por usuario, algunos dirían que la opción obvia sería nombrar el archivo de la misma manera que la identificación de los usuarios.
Alan Barber el
la marca de tiempo no es una buena idea, porque DateTime.Now se actualiza solo cada 15 ms. Hay una alta posibilidad de colisión, por ejemplo, durante la carga masiva, las solicitudes en cola, etc.
jhexp

Respuestas:

27

Debes tratar de alcanzar dos objetivos: singularidad y utilidad.

El uso de un GUID garantiza la unicidad, pero un día los archivos pueden separarse de su fuente original, y luego tendrá problemas.

Mi solución típica es incrustar información crucial en el nombre del archivo, como el ID de usuario (si pertenece a un usuario) o la fecha y hora cargadas (si esto es significativo), o el nombre de archivo utilizado al cargarlo.

Esto realmente puede salvar su aspecto un día, cuando la información incrustada en el nombre del archivo le permite, por ejemplo, recuperarse de un error o la eliminación accidental de registros. Si todo lo que tienes son GUID, y pierdes el catálogo, tendrás un gran trabajo limpiando eso.

Por ejemplo, si se carga un archivo "My Holiday: Florida 23.jpg", con el ID de usuario 98765, el 04/04/2013 a las 12:51:23 lo nombraría así, agregando una cadena aleatoria ad8a7dsf9:

20130404125123-ad8a7dsf9-98765-my-holiday-florida-23.jpg

  • La unicidad está garantizada por la fecha y la hora, y la cadena aleatoria (siempre que sea correctamente aleatoria de / dev / urandom o CryptGenRandom.
  • Si alguna vez se separa el archivo, puede identificar al usuario, la fecha y la hora, y el título.
  • Todo está doblado en minúsculas y todo lo que no sea alfanumérico se elimina y reemplaza por guiones, lo que hace que el nombre de archivo sea fácil de manejar con herramientas simples (por ejemplo, sin espacios que puedan confundir los scripts mal escritos, sin dos puntos u otros caracteres que están prohibidos en algunos sistemas de archivos , y así).
Ben
fuente
77
Por el bien de la limpieza, recomendaría crear directorios separados por ID de usuario para que si elimina un usuario no tenga que buscar todas sus imágenes. - entonces98765/20130404125123-ad8a7dsf9-my-holiday-florida-23.jpg
Shadur
1
Teóricamente, la unicidad no proporciona la unicidad.
Kolyunya
44
@Kolyuny, eso es cierto, en el sentido de que la unicidad global garantizada no es una propiedad que incluso los GUID tienen en la vida real (incluso las guías v1 se rompen debido a la emisión de direcciones MAC duplicadas). Todo lo que puede obtener es una probabilidad estadística de unicidad. Pero puede garantizar la unicidad verificando si el archivo ya existe (usando atómicamente CreateFilecon CREATE_NEW), y usando una aleatoriedad diferente si es así.
Ben
'Todo está doblado en minúsculas y todo lo que no sea alfanumérico se elimina y se reemplaza por guiones', lo mantendría en mayúsculas y minúsculas, eliminaría todos los
números
4

No desea estresar las aplicaciones (como Explorer) y hacer que se bloquee al abrir el directorio. Si bien es poco probable que estreses el sistema de archivos real, debes tener esto en cuenta si vas a almacenar miles de archivos.

Si espera almacenar miles de archivos, mi sugerencia es particionar en carpetas. Por ejemplo upload\silo001, upload\silo002etc. Puede equilibrar sus archivos o esperar hasta que una carpeta llegue a un cierto número de archivos y luego crear otro.

Con respecto a los nombres, siempre nombro un archivo con un GUID porque es globalmente único. Extraigo la extensión de la carga y configuro la extensión del archivo para que coincida, pero el nombre real se establece desde un nuevo Guid.

Si está haciendo esto junto con un RDBMS y tiene varias categorías, es decir, productos, categorías, etc. que podría tener upload\products, upload\categoriesetc., y podría usar la ID de fila como nombre de archivo.

En términos de mejores prácticas, yo también he buscado en el pasado y no he encontrado nada. Se me ocurrió lo anterior mientras discutía con algunos de mis desarrolladores.

Sam
fuente
2

En una de las soluciones en las que trabajé hace años, hicimos esto: subcarpetas para parte de la identificación de usuario, por lo que si su identificación de usuario era 232950192

tendríamos imágenes de subcarpetas / 23/29/50/192/232950192

en la carpeta final tiene carpetas para albuns e imgs de perfil, etc.

Pero también guardamos todo en la base de datos y lo guardamos en el sistema de archivos para acceder rápidamente al servidor web (que también tiene almacenamiento en caché)

De todos modos, la imagen final tendría el nombre de la imagen original. No necesitábamos mantener versiones. Pero para lo que puede mantener más subcarpetas debajo de los nombres finales del álbum o en la base de datos con una identificación de versión. es necesario pensarlo bien, ya que una vez que pasa a producción sería difícil cambiar las cosas sin perder tiempo y correcciones propensas a errores en la estructura actual

Es muy fácil hacer una subcarpeta en Java y crear un archivo en ella:

    File folder = new File(pathwithslashes);// like "images/23/29/50/192/232950192"
    folder.mkdirs();
    File imgFile = new File(folder, name);
    //Now get output stream etc

Para obtener el sello de fecha en subcarpetas: SimpleDateFormat sdf = new SimpleDateFormat ("/ aaaa / MM / dd /"); pathwithslashes = pathwithslashes + sdf.format (ahora); // ahora es una carpeta de archivo util.Date = nuevo archivo (pathwithslashes);

Dot net /programming/5482230/c-sharp-equivalent-of-javas-mkdirs

revs tgkprog
fuente
+1 por sugerir directorios anidados. Creo que esto es importante tener en cuenta que diferentes sistemas de ficheros pueden encontrar problemas de rendimiento cuando las carpetas contienen "demasiados" archivos: stackoverflow.com/questions/197162/... , support.microsoft.com/kb/130694/en-us , etc.
deizel
1
sí en otro sistema tenía uno de los servidores web bloqueados cuando intentamos ejecutar en un directorio que tenía más de 400,000 archivos. Teníamos más carpetas como esta. entonces usé un programa personalizado que llamaba dir / p para obtener algunos archivos para eliminarlos a la vez. tomó algunas horas pero no tiempo de inactividad :)
tgkprog
1

Recomiendo usar solo md5 o cualquier cosa conceptualmente equivalente. Al renombrar archivos por resumen de su contenido, no solo está otorgando exclusividad (siempre almacena en caché las imágenes durante el mayor tiempo posible, y con el cambio de nombre basado en contenido, bueno, con el correcto, puede almacenar en caché las imágenes prácticamente para siempre).

Además, no es gran cosa, pero no es un caso hipotético puro cuando diferentes usuarios cargan exactamente la misma imagen. Recién listo, tendrá una pequeña optimización de almacenamiento de datos.

En cuanto a cualquier otra cosa propuesta: en cuanto a mí, soy un fuerte oponente de mantener cualquier tipo de información auxiliar en un nombre de archivo. Cuando era mucho más joven (y un poco más delgado :), era un desarrollador de Perl y tenía la dudosa costumbre de almacenar tanta información auxiliar en el nombre del archivo como me permitía el sentido común, ya que las características del patrón de cadena de Perl son impresionantes. Y llegué a la conclusión de que, hablando de desarrollo web, siempre es una mejor opción mantener los datos asociados con el archivo por separado del nombre del archivo.

Tenga en cuenta que hoy en día, cuando dominan las interfaces móviles, el nombre real del archivo es algo menos importante que hace 5, 10 años. Pero incluso si esto será crucial en el contexto de su aplicación, siempre puede involucrar un poco de magia de la vieja escuela con la participación del Content-Disposition: attachment; filename="pretty_file_name.jpg"encabezado HTTP, construyendo cualquier nombre de archivo relevante que desee. Además, los navegadores modernos están allanando el camino para el nuevo atributo HTML5, descargar . No creo que ver el nombre de la imagen "legible para humanos" sea algo en lo que deba pensar en la mayoría de los casos.

UPD: Se puede hacer una modificación para no tener demasiados archivos en un directorio, solo tome las primeras 3 letras y cree el directorio.

shabunc
fuente
1
¿es md5 realmente único?
I.devries
@ I.devries, no soy un especialista, pero que yo sepa, es lo suficientemente bueno para este propósito. Sobre todo si, además, podrás comprobar el tamaño del archivo, ya que el algoritmo de hash buena realidad conceder que las entidades del mismo tamaño será menos probable que tenga una colisión - stackoverflow.com/questions/2442632/...
shabunc
-1

Las posibilidades de colisiones con algo como sha4 son infinitesimales. Si combina el hash con el ID de usuario o incluso una fecha simple, aún menos.

Evan Zamir
fuente