Qual é o melhor local para armazenar imagens carregadas, banco de dados SQL ou sistema de arquivos em disco?

146

Estou escrevendo um aplicativo que permite aos usuários fazer upload de imagens no servidor. Espero cerca de 20 imagens por dia todos os JPEG e provavelmente não editados / redimensionados. (Essa é outra questão: como redimensionar as imagens no servidor antes de armazenar. Talvez alguém possa soltar um recurso .NET para isso no comentário). Gostaria de saber agora qual é o melhor lugar para armazenar imagens carregadas.

  • Armazene as imagens como um arquivo no sistema de arquivos e crie um registro em uma tabela com o caminho exato para essa imagem.

  • Ou armazene a própria imagem em uma tabela usando um tipo de dados "imagem" ou "dados binários" do servidor de banco de dados.

Vejo vantagens e desvantagens em ambos. Gosto de a) porque posso realocar facilmente os arquivos e apenas preciso alterar a entrada da tabela. Por outro lado, não gosto de armazenar dados corporativos no servidor Web e não quero realmente conectar o servidor Web a qualquer outra fonte de dados que armazene dados corporativos (por motivos de segurança). Gosto de b) porque todas as informações são em um só lugar e facilmente acessível por uma consulta. Por outro lado, o banco de dados ficará muito grande muito em breve. Terceirizar esses dados pode ser mais difícil.

Tobias
fonte
2
Não encontrei, onde?
Tobias
6
Aqui stackoverflow.com/questions/3748/…
jason saldo 8/08/08

Respostas:

95

Geralmente armazeno arquivos no sistema de arquivos, pois é para isso que existe, embora haja exceções. Para arquivos, o sistema de arquivos é a solução mais flexível e com melhor desempenho (geralmente).

Existem alguns problemas com o armazenamento de arquivos em um banco de dados - os arquivos geralmente são muito maiores que a linha média - os conjuntos de resultados que contêm muitos arquivos grandes consomem muita memória. Além disso, se você usar um mecanismo de armazenamento que utilize bloqueios de tabela para gravações (ISAM, por exemplo), sua tabela de arquivos poderá ser bloqueada frequentemente, dependendo do tamanho / taxa de arquivos que você está armazenando lá.

Em relação à segurança - geralmente armazeno os arquivos em um diretório que está fora da raiz do documento (não acessível por meio de uma solicitação http) e os sirvo através de um script que verifica primeiro a devida autorização.

Eran Galperin
fonte
7
Você poderia me explicar o último parágrafo (em relação à segurança) em termos de detalhes técnicos ou qualquer indicação seria muito útil. Obrigado.
VishwaKumar #
39
(Para todos os googlers por aí) Se você tiver a raiz do seu site configurada para uma pasta "pública" (como em my_website / public / em vez de apenas my_website /), poderá armazenar as imagens na pasta my_website / my_images com o restante de seu aplicativo. Suas tags img referenciam "my_website / image.php? Img_id = 55" em vez de "my_website / avatar.png", e seu script image.php, após verificar suas credenciais e analisar o ID que você entrega, retorna o valor real imagem. Dessa forma, a imagem é visível apenas pelo usuário logado adequado.
Captain Hypertext
8
Hey capitão você deve transformar isso em uma resposta real para que você pode obter pontos $$$
Andrew
4
por favor, adicione mais algumas notas sobre segurança / impedir que arquivos destruam seu site
Andrew
1
Isso não seria escalável, há um limite para o número de arquivos na pasta e, se você planeja dividir seus arquivos em várias pastas, adicionará complexidades de indexação dos arquivos (para identificar onde o arquivo está realmente armazenado). Além disso, a pesquisa será muito lenta.
Hardik
43

O único benefício para a opção B é ter todos os dados em um sistema, mas é um benefício falso! Você pode argumentar que seu código também é uma forma de dados e, portanto, também pode ser armazenado no banco de dados - como você gostaria?

A menos que você tenha algum caso exclusivo:

  • A lógica de negócios pertence ao código.
  • Os dados estruturados pertencem ao banco de dados (relacional ou não relacional).
  • Os dados em massa pertencem ao armazenamento (sistema de arquivos ou outro).

Arquivos, Código, Dados

Não é necessário usar o sistema de arquivos para manter os arquivos. Em vez disso, você pode usar o armazenamento em nuvem (como o Amazon S3 ) ou a infraestrutura como serviço em cima dele (como o Uploadcare ):

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

Mas armazenar arquivos no banco de dados é uma má idéia.

David Avsajanishvili
fonte
23

O Flickr usa o sistema de arquivos - eles discutem os motivos aqui

Martin Beckett
fonte
14

Eu sei que este é um post antigo. Mas muitos visitantes desta página não estão recebendo nada relacionado à pergunta. Especialmente para um novato.

Como fazer upload e armazenar imagens ou arquivos em nosso site:

Para um site estático, talvez não haja problema, pois o armazenamento de arquivos para alguns compartilhamentos de hospedagem ainda é adequado. O problema vem de um site dinâmico quando fica maior. Maiores no banco de dados podem ser manipulados, mas arquivos maiores, como imagens, tornam-se um problema. Existem dois tipos de imagens em um site:

  1. As imagens são do administrador do blog dinâmico. Geralmente, essas imagens são otimizadas antes do upload.

  2. Imagens de usuários no caso de usuários podem fazer upload de imagens como avatar. Ou os usuários podem criar conteúdo do blog e colocar algumas imagens do editor de texto. Esse tipo de imagem é difícil de prever o tamanho. Os usuários podem fazer upload de imagens grandes apenas para conteúdo pequeno, redimensionando o tamanho da visualização, mas não redimensionando o tamanho da imagem.

Ignorando o item no. 1 acima, solução rápida para o item no. 2 pode ser resolvido temporariamente pelas seguintes dicas, se não tivermos a funcionalidade otimizador de imagem em nosso site:

  1. Não permita que os usuários enviem diretamente do editor de texto, redirecionando-os para a galeria de imagens. Nesta página, os usuários devem fazer upload do arquivo com antecedência antes de poderem incorporar o conteúdo. Este método é chamado como um gerenciador de arquivos.

  2. Use uma função de corte de imagem para os usuários fazerem upload de imagens. Isso limitará o tamanho da imagem, mesmo que os usuários enviem arquivos muito grandes. A imagem final é o resultado da imagem cortada. Podemos definir o tamanho no servidor e aceitar apenas, por exemplo, 500 KB ou menos.

Agora, isso é apenas temporário. Para solução final, a pergunta é repetida:

  • Como lidar com um armazenamento de imagens grandes?
  • Redimensione ou altere a extensão.
  • Como um site ou comércio eletrônico grande ou médio lida com o armazenamento de arquivos de suas imagens?

O que podemos fazer então:

  1. Migrar do compartilhamento de hospedagem VPS. Insuficiente? Mais ainda, atualizando para Dedicado.

  2. Crie seu próprio servidor para armazenamento de arquivos. Pesquisando para fazer isso. Isso não é tão difícil quanto você pensa. Algumas pessoas fazem isso pelo site.

  3. A maneira mais fácil é usar o serviço de armazenamento de arquivos CDN.

Ok, 1 e 2 é um pouco caro. Mas no 3 eu acho que é a melhor solução.

Alguns serviços CDN permitem armazenar quantos arquivos da web você desejar.

Pergunta, "como fazer upload de arquivo para CDN do nosso site?"

Não se preocupe, depois de se registrar, geralmente de graça, você receberá orientações sobre como fazer upload de arquivos e obter o link deles de / para o seu site. Você receberá uma API e muito mais. É fácil.

Alguns provedores nos oferecem um serviço gratuito por 14 dias, com armazenamento e largura de banda limitados. Mas tudo bem como ponto de partida. O único problema é porque 'as pessoas nunca tentam'.

Espero que ajude para iniciantes.

Sulung Nugroho
fonte
13

Tivemos clientes insistindo na opção B (armazenamento de banco de dados) algumas vezes em alguns back-end diferentes, e sempre acabamos voltando à opção A (armazenamento do sistema de arquivos).

BLOBs grandes como esse simplesmente não foram tratados o suficiente, mesmo pelo SQL Server 2005, que é o mais recente em que testamos.

Especificamente, vimos inchaço grave e acho que talvez tenha problemas de bloqueio.

Outra observação: se você estiver usando armazenamento baseado em NTFS (servidor Windows, etc), considere encontrar uma maneira de colocar milhares e milhares de arquivos em um diretório. Não sei por que, mas às vezes o sistema de arquivos não lida bem com essa situação. Se alguém souber mais sobre isso, eu adoraria ouvir.

Mas eu sempre tento usar subdiretórios para quebrar um pouco as coisas. A data de criação geralmente funciona bem para isso:

Images / 2008/12/17 / .jpg

... Isso fornece um nível decente de separação e também ajuda um pouco durante a depuração. Os clientes Explorer e FTP podem engasgar um pouco quando há diretórios realmente grandes.

EDIT: Apenas uma observação rápida para 2017, nas versões mais recentes do SQL Server, há novas opções para lidar com muitos BLOBs que devem evitar as desvantagens que discuti.

EDIT: Observação rápida para 2020, o Armazenamento de Blob no AWS / Azure / etc também é uma opção há anos. Isso é ideal para muitos projetos baseados na Web, pois é barato e muitas vezes pode simplificar certos problemas de implantação, dimensionamento para vários servidores, depuração de outros ambientes quando necessário etc.

Brian MacKay
fonte
4
Bom aviso sobre o número de arquivos no mesmo diretório. Isso pode dificultar a localização de erros em um ambiente de produção.
digao_mb
1
Eu já havia atingido esse problema antes. O NTFS se comportou de maneira imprevisível com cerca de 10.000 arquivos em uma pasta.
Faiz
1
Não apenas NTFS, mas também BTRFS, que também tem um problema ao lidar com grandes quantidades de imagens em uma pasta. Ou seja, se você tentasse ls, levaria uma eternidade (trava). Ou exclua.
sunapi386
11

Recentemente, criei um aplicativo PHP / MySQL que armazena arquivos PDF / Word em uma tabela MySQL (até 40 MB por arquivo até agora).

Prós:

  • Os arquivos enviados são replicados para o servidor de backup, juntamente com todo o resto, não sendo necessária nenhuma estratégia de backup separada (tranqüilidade).
  • A configuração do servidor da Web é um pouco mais simples, porque não preciso ter uma pasta / uploads e informar todos os meus aplicativos onde ele está.
  • Uso transações para fazer edições para melhorar a integridade dos dados - não preciso me preocupar com arquivos órfãos e ausentes

Contras:

  • O mysqldump agora demora muito, porque há 500 MB de dados de arquivo em uma das tabelas.
  • No geral, não é muito eficiente em termos de memória / CPU quando comparado ao sistema de arquivos

Eu consideraria minha implementação um sucesso, ele cuida dos requisitos de backup e simplifica o layout do projeto. O desempenho é bom para as 20 a 30 pessoas que usam o aplicativo.

muito php
fonte
6

Eu uso imagens carregadas no meu site e definitivamente diria a opção a).

Outra coisa que eu recomendo é mudar imediatamente o nome do arquivo do nome que o usuário deu à foto, para algo mais gerenciável. Por exemplo, algo com a data e a hora para identificar exclusivamente cada imagem.

Também ajuda a remover o nome de arquivo do usuário de caracteres estranhos para evitar complicações futuras.

barfoon
fonte
6

Definitivamente redimensione a imagem e verifique seu formato, se puder. Houve casos de arquivos maliciosos sendo carregados e servidos por hosts involuntários - por exemplo, a vulnerabilidade GIFAR permitiu ocultar um applet java malicioso em um arquivo GIF, que seria capaz de ler cookies no contexto atual e enviá-los para outro site para um ataque de script entre sites. O redimensionamento das imagens geralmente evita isso, uma vez que mescla o código incorporado. Embora esse ataque tenha sido corrigido pelos patches da JVM, o fornecimento ingênuo de arquivos binários sem limpá-los abre uma grande variedade de vulnerabilidades.

Lembre-se de que a maioria dos scanners de vírus pode ser executada apenas no sistema de arquivos. Se você armazenar seus binários no banco de dados, não poderá executar um scanner contra eles com muita facilidade.

Tim Howland
fonte
4

Isso é basicamente o que faço.

  1. Armazene uma imagem carregada no diretório ou na memória temporária.
  2. Processe essa imagem antes de armazená-la permanentemente. 2.1 Correções de cores 2.2. Comprimir 2.3. Crie várias cópias com base nas dimensões da imagem 2.4. Renomeie com sufixos .xl, .lg, .md, .sm etc.
  3. Empacote todos os arquivos de imagem processados ​​(de um único arquivo) dentro de uma pasta com o nome da pasta, idque será armazenada no banco de dados para qualquer linha / documento, juntamente com image file name(ou pode ser um nome aleatório como nome da imagem).
  4. Crie uma pasta aaaa / mm / d, path se não existir. Por exemplo, 21/08/2016. Lembre-se desse caminho e armazene no banco de dados para o mesmo documento e linha.
  5. Mova a idpasta da imagem para a pathpasta. (A pasta Path pode estar localizada na pasta / var / conteúdo da web.)
  6. Limpe o buffer de memória ou exclua o arquivo temporário.

Quando você precisa acessar qualquer imagem mencionada em um documento, possui o caminho e o ID da pasta que contém imagens. Por exemplo/var/web-content/{{path}}/{{id}}/image-file-name.sm.jpg

Dessa forma, se você precisar excluir todos os arquivos de imagem processados, exclua a pasta e seu conteúdo recursivamente.

Uday Hiwarale
fonte
3

A maioria das implementações é a opção A.

Com a opção B, você abre uma grande lata de whoop4ss ao organizar esses bits do banco de dados em algo que pode ser exibido em um navegador ... Além disso, se o banco de dados estiver inativo, as imagens não estarão disponíveis.

Eu não acho que o espaço seja muito problemático ... Os discos Terabyte custam algumas centenas de dólares agora.

Estamos implementando com a opção A porque não temos tempo ou recursos para executar a opção B.

mson
fonte
3

Para redimensionamento automático, tente o imagemagick ... é usado para muitos dos principais sistemas de gerenciamento de conteúdo / foto de código aberto ... e acredito que existem algumas extensões .net para ele.

jle
fonte
2

Usamos A. Eu o colocaria em uma unidade compartilhada (a menos que você não planeje executar mais de um servidor).

Se chegar o momento em que isso não será dimensionado para você, você poderá investigar os mecanismos de cache.

Csexton
fonte
2

Absolutamente, opção positiva A. Outros mencionaram que os bancos de dados geralmente não lidam bem com BLOBs, sejam eles projetados para fazê-lo ou não. Os sistemas de arquivos, por outro lado, vivem desse tipo de coisa. Você tem a opção de usar faixas RAID, espalhar imagens por várias unidades, até espalhá-las por servidores geograficamente diferentes.

Outra vantagem é que os backups / replicação do banco de dados seriam monstruosos.

dj_segfault
fonte
2

Por motivos de segurança, também é uma prática recomendada evitar problemas causados ​​pelo Sniffing de conteúdo do IE, que pode permitir que invasores enviem JavaScript dentro de arquivos de imagem, que podem ser executados no contexto do seu site. Portanto, convém transformar as imagens (cortá-las / redimensioná-las) de alguma forma antes de armazená-las para evitar esse tipo de ataque. Esta resposta tem algumas outras idéias.

Dia
fonte
2

Bem, eu tenho um projeto semelhante no qual os usuários enviam arquivos para o servidor. Do meu ponto de vista, a opção a) é a melhor solução devido à sua flexibilidade. O que você deve fazer é armazenar imagens em uma pasta protegida classificada por subdiretórios. O diretório principal deve ser configurado pelo administrador, pois o conteúdo não deve executar scripts (muito importantes) e (ler, escrever) protegidos para não serem acessíveis na solicitação http.

Espero que isso ajude você.

domoindal
fonte
1

Se forem arquivos pequenos que não precisarão ser editados, a opção B não será uma má opção. Eu prefiro isso a escrever lógica para armazenar arquivos e lidar com problemas de estrutura de diretórios malucos. Ter muitos arquivos em um diretório é ruim. emkay?

Se os arquivos forem grandes ou exigirem edição constante, especialmente de programas como o office, a opção A é sua melhor aposta.

Na maioria dos casos, é uma questão de preferência, mas se você optar pela opção A, faça com que os diretórios não possuam muitos arquivos. Se você escolher a opção B, faça com que a tabela com os dados de BLOB esteja em seu próprio banco de dados e / ou grupo de arquivos. Isso ajudará na manutenção, especialmente nos backups / restaurações. Seus dados regulares são provavelmente bastante pequenos, enquanto os dados da imagem serão enormes com o tempo.

Charles Graham
fonte
1

Depende de seus requisitos, especialmente volume, usuários e frequência de pesquisa. Porém, para escritórios pequenos ou médios, a melhor opção é usar um aplicativo como o Apple Photos ou o Adobe Lighroom. Eles são especializados para armazenar, catalogar, indexar e organizar esse tipo de recurso. Porém, para grandes organizações, com fortes requisitos de armazenamento e alto número de usuários, é recomendável instanciar uma plataforma de Gerenciamento de Conteúdo com um Gerenciamento de Ativos Digitais, como Nuxeo ou Alfresco; ambas oferecem recursos muito bons; gerenciam grandes volumes de dados com métodos simplificados para recuperá-los. E, muito importante: existe uma opção gratuita (de código aberto) para ambas as plataformas.

Carlos Camargo
fonte