Qual é a melhor prática para nomear imagens carregadas?

15

Suponha que eu tenha um formulário no meu aplicativo Web em que os usuários possam fazer upload de uma foto do perfil.

Tenho poucos requisitos sobre tamanho de arquivo, dimensões, etc., mas quando o usuário carrega a imagem, como devo nomeá-los no meu sistema? Suponho que precisaria ser consistente e também único.

Talvez um GUID?

a5c627bedc3c44b7ae7c06a44fb3fcf8.jpg

Um timestamp?

129899740140465735.jpg

Um hash? Ex: md5

b1a9acaf295cf14ffbc5b6538294562c.jpg

Existe uma maneira padrão ou recomendada de fazer isso?

Rowan Freeman
fonte
7
Se seu objetivo é armazenar apenas uma foto de perfil por usuário, alguns diriam que a escolha óbvia seria nomear o arquivo da mesma forma que a identificação do usuário.
Alan Barber
timestamp não é uma boa ideia, porque o DateTime.Now é atualizado apenas a cada 15ms. Há uma grande chance de colisão, por exemplo, durante bulkload, em fila pedidos etc ..
jhexp

Respostas:

27

Você deve tentar atingir dois objetivos: Exclusividade e utilidade.

O uso de um GUID garante exclusividade, mas um dia os arquivos podem ser desanexados da fonte original e você terá problemas.

Minha solução típica é incorporar informações cruciais no nome do arquivo, como o ID do usuário (se pertencer a um usuário) ou a data e hora do upload (se isso for significativo) ou o nome do arquivo usado ao enviá-lo.

Isso pode realmente salvar a sua pele um dia, quando as informações incorporadas no nome do arquivo permitem, por exemplo, recuperar-se de um bug ou excluir acidentalmente os registros. Se tudo o que você tem são GUIDs e você perde o catálogo, você terá um trabalho bem feito para limpá-lo.

Por exemplo, se um arquivo "My Holiday: Florida 23.jpg" for carregado, pelo ID do usuário 98765, em 04/04/2013 às 12:51:23, eu o chamaria assim, adicionando uma sequência aleatória ad8a7dsf9:

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

  • A exclusividade é garantida pela data e hora e pela sequência aleatória (desde que seja adequadamente aleatória em / dev / urandom ou CryptGenRandom.
  • Se o arquivo for desanexado, você poderá identificar o usuário, a data, a hora e o título.
  • Tudo é dobrado para minúsculo e qualquer coisa não alfanumérica é removida e substituída por traços, o que facilita o manuseio do nome de arquivo usando ferramentas simples (por exemplo, nenhum espaço que possa confundir scripts mal escritos, dois pontos ou outros caracteres que são proibidos em alguns sistemas de arquivos , e assim por diante).
Ben
fonte
7
Por questões de limpeza, recomendo a criação de diretórios separados por ID do usuário, para que, se você excluir um usuário, não precise procurar todas as imagens. - assim98765/20130404125123-ad8a7dsf9-my-holiday-florida-23.jpg
Shadur
1
Teoricamente, a exclusividade não é fornecida pela sequência aleatória.
Kolyunya
4
@Kolyuny, isso é verdade, no sentido de que a exclusividade global garantida não é uma propriedade que até os GUIDs tenham na vida real (até mesmo os guias v1 são impedidos devido à emissão de endereços MAC duplicados). Tudo o que você pode obter é uma probabilidade estatística de exclusividade. Mas você pode garantir a exclusividade verificando se o arquivo já existe (usando atomicamente CreateFilecom CREATE_NEW) e usando aleatoriedade diferente, se existir.
Ben
'Tudo é dobrado para minúsculas e qualquer coisa não alfanumérica é removida e substituída por traços', eu manteria em maiúsculas e minúsculas, removeria todos os
números
4

Você não quer estressar os aplicativos (como o Explorer) e causar falhas quando abrir o diretório. Embora seja improvável que você estresse o sistema de arquivos real, é necessário levar isso em consideração se estiver armazenando milhares de arquivos.

Se você espera armazenar milhares de arquivos, minha sugestão é particionar em pastas. Por exemplo upload\silo001, upload\silo002etc. Você pode equilibrar seus arquivos ou aguardar até que uma pasta atinja um determinado número de arquivos e depois criar outro.

No que diz respeito à nomeação, eu sempre nomeio um arquivo com um GUID porque é globalmente exclusivo. Pego a extensão do upload e defino a extensão do arquivo para corresponder, mas o nome real é definido em um novo Guid.

Se você estiver fazendo isso em conjunto com um RDBMS e tiver várias categorias, por exemplo, produtos, categorias, etc., poderá ter upload\products, upload\categoriesetc., e poderá usar o ID da linha como o nome do arquivo.

Em termos de melhores práticas, eu também procurei no passado e não encontrei nada. Eu vim com o acima exposto enquanto discutia com alguns dos meus desenvolvedores.

Sam
fonte
2

Em uma das soluções em que trabalhei anos atrás, fizemos o seguinte: subpastas para parte do ID do usuário, portanto, se o seu ID de usuário era 232950192

teríamos subpastas images / 23/29/50/192/232950192

na pasta final tem pastas para álbuns e imagens de perfil etc.

Mas também salvamos tudo no banco de dados e o mantemos no sistema de arquivos para acesso rápido ao servidor da Web (que também possui armazenamento em cache)

De qualquer forma, a imagem final teria o nome da imagem original. Não precisamos manter as versões. Mas para o que pode manter mais subpastas sob os nomes finais do álbum ou na base de dados com um ID de versão. é preciso pensar nisso uma vez que, uma vez que seja direcionado à produção, seria difícil mudar as coisas sem consumir tempo e correções propensas a erros na estrutura atual

É muito fácil criar uma subpasta em java e criar um arquivo nela:

    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 obter o carimbo de data nas subpastas: SimpleDateFormat sdf = new SimpleDateFormat ("/ aaaa / MM / dd /"); pathwithslashes = pathwithslashes + sdf.format (now); // now is a util.Date Pasta do arquivo = new File (pathwithslashes);

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

tgkprog
fonte
+1 por sugerir diretórios aninhados. Eu acho que isso é importante considerar, pois sistemas de arquivos diferentes podem encontrar problemas de desempenho quando as pastas contêm arquivos "muitos": stackoverflow.com/questions/197162/… , support.microsoft.com/kb/130694/en-us etc.
deizel 04/04
1
Sim, em outro sistema, houve um travamento do servidor da Web quando tentamos rmdir em um diretório que tinha mais de 400.000 arquivos. tínhamos mais pastas assim. então, usou um programa personalizado que chamou dir / p para obter alguns arquivos para excluir por vez. levou algumas horas mas não há tempo para baixo :)
tgkprog
1

Eu recomendaria usar apenas MD5 ou qualquer coisa conceitualmente equivalente. Ao renomear arquivos pelo resumo do conteúdo, você não apenas concede exclusividade (sempre armazene em cache as imagens pelo maior tempo possível e com a renomeação baseada em conteúdo, bem, com uma adequada, é possível armazenar em cache as imagens praticamente para sempre).

Além disso, não é grande coisa, mas, no entanto, não é um caso hipotético puro quando usuários diferentes carregam exatamente a mesma imagem. Apenas pronto para o uso, você terá uma pequena otimização do armazenamento de dados.

Quanto a qualquer outra coisa proposta: quanto a mim, sou um forte oponente em manter qualquer tipo de informação auxiliar em um nome de arquivo. Quando eu era muito mais jovem (e um pouco mais magro :), eu era um desenvolvedor de Perl e tinha o hábito duvidoso de armazenar tantas informações auxiliares no nome de arquivo quanto o senso comum me permitia, já que os recursos de padrão de string do Perl são impressionantes. E cheguei à conclusão de que, falando em desenvolvimento web, é sempre melhor escolher manter os dados associados ao arquivo separadamente do nome do arquivo.

Lembre-se de que hoje em dia, quando as interfaces móveis estão dominando, o nome real do arquivo é menos importante do que há 5, 10 anos atrás. Mas mesmo que isso seja crucial no contexto de sua aplicação, você sempre pode envolver alguma mágica da velha escola com o envolvimento do Content-Disposition: attachment; filename="pretty_file_name.jpg"cabeçalho HTTP, construindo qualquer nome de arquivo relevante que desejar. Além disso, os navegadores modernos estão abrindo caminho para o novo atributo HTML5, o download . Não acredito que realmente ver o nome da imagem "legível por humanos" seja algo que você deva pensar na maioria dos casos.

UPD: Uma modificação pode ser feita para não haver muitos arquivos em um diretório - basta pegar as 3 primeiras letras e criar o diretório.

shabunc
fonte
1
MD5 é realmente único embora?
precisa saber é o seguinte
@ I.devries, não sou especialista, mas, tanto quanto sei, é bom o suficiente para esse fim. Especialmente se você vai além disso verificar o tamanho do arquivo, uma vez que o algoritmo de hash boa realmente conceder que as entidades do mesmo tamanho será menos provavelmente tem uma colisão - stackoverflow.com/questions/2442632/...
shabunc
-1

As chances de colisões com algo como sha4 são infinitesimais. Se você combinar o hash com o ID do usuário ou mesmo uma data simples, menos ainda.

Evan Zamir
fonte