Qual è il posto migliore per archiviare immagini caricate, database SQL o file system su disco?


147

Sto scrivendo un'applicazione che consente agli utenti di caricare immagini sul server. Mi aspetto circa 20 immagini al giorno tutte jpeg e probabilmente non modificate / ridimensionate. (Questa è un'altra domanda, come ridimensionare le immagini sul lato server prima di archiviarle. Forse qualcuno può rilasciare una risorsa .NET per quello nel commento o giù di lì). Ora mi chiedo quale sia il posto migliore per archiviare le immagini caricate.

  • Archivia le immagini come file nel file system e crea un record in una tabella con il percorso esatto per quell'immagine.

  • In alternativa, archiviare l'immagine stessa in una tabella utilizzando un tipo di dati "immagine" o "dati binari" del server di database.

Vedo vantaggi e svantaggi in entrambi. Mi piace a) perché posso spostare facilmente i file e devo solo cambiare la voce della tabella. D'altra parte non mi piace archiviare i dati aziendali sul server Web e non voglio davvero connettere il server Web a qualsiasi altra origine dati che contiene dati aziendali (per motivi di sicurezza) mi piace b) perché tutte le informazioni sono in un unico posto e facilmente accessibile da una query. D'altra parte il database diventerà molto grande molto presto. Esternalizzare quei dati potrebbe essere più difficile.


2
Non l'ho trovato, dove?
Tobias,


Risposte:


95

Di solito conservo i file sul file system, dato che è quello che serve, anche se ci sono eccezioni. Per i file, il file system è la soluzione più flessibile e performante (di solito).

Esistono alcuni problemi con l'archiviazione dei file in un database - i file sono generalmente molto più grandi della riga media - i set di risultati contenenti molti file di grandi dimensioni consumano molta memoria. Inoltre, se si utilizza un motore di archiviazione che utilizza i blocchi di tabelle per le scritture (ad esempio ISAM), la tabella dei file potrebbe essere bloccata spesso a seconda della dimensione / velocità dei file che si stanno archiviando lì.

Per quanto riguarda la sicurezza, di solito conservo i file in una directory esterna alla radice del documento (non accessibile tramite una richiesta http) e li offro tramite uno script che verifica prima la corretta autorizzazione.


7
Potresti spiegarmi l'ultimo paragrafo (Per quanto riguarda la sicurezza) in termini di dettagli tecnici o eventuali suggerimenti sarebbe molto utile. Grazie.
VishwaKumar,

39
(Per tutti i googler là fuori) Se hai la radice del tuo sito configurata su una cartella "pubblica" (come in my_website / public / anziché solo my_website /), puoi archiviare le immagini nella cartella my_website / my_images con il resto di la tua app. Quindi i tuoi tag img farebbero riferimento a "my_website / image.php? Img_id = 55" invece di "my_website / avatar.png", e il tuo script image.php farebbe, dopo aver verificato le tue credenziali e analizzato l'id che le hai passato, restituirà l'effettivo Immagine. In questo modo, l'immagine è visualizzabile solo dall'utente che ha effettuato l'accesso.
Capitano Hypertext

8
ehi capitano, dovresti trasformarlo in una vera risposta in modo da poter ottenere punti $$$
Andrew

4
si prega di aggiungere alcune note in più sulla sicurezza / impedire ai file di distruggere il tuo sito Web
Andrew

1
Ciò non si ridimensionerebbe, esiste un limite al numero di file nella cartella e se si prevede di dividere i file in più cartelle, si aggiungerebbero complessità di indicizzazione dei file (per identificare dove è effettivamente archiviato il file). Inoltre, la ricerca sarà molto lenta.
Hardik,

43

L'unico vantaggio per l'opzione B è avere tutti i dati in un sistema, ma è un falso vantaggio! Potresti sostenere che il tuo codice è anche una forma di dati e quindi può anche essere archiviato nel database: come ti piacerebbe?

A meno che tu non abbia un caso unico:

  • La logica aziendale appartiene al codice.
  • I dati strutturati appartengono al database (relazionale o non relazionale).
  • I dati in blocco appartengono alla memoria (filesystem o altro).

File, codice, dati

Non è necessario utilizzare il filesystem per conservare i file. Invece puoi utilizzare l'archiviazione cloud (come Amazon S3 ) o Infrastruttura come servizio (come Uploadcare ):

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

Ma archiviare i file nel database è una cattiva idea.



14

So che questo è un vecchio post. Ma molti visitatori di questa pagina non ottengono nulla in relazione alla domanda. Soprattutto per un principiante.

Come caricare e archiviare immagini o file nel nostro sito Web:

Per un sito Web statico forse non ci sono problemi poiché l'archiviazione dei file per alcuni hosting condivisi è ancora adeguata. Il problema nasce da un sito Web dinamico quando diventa più grande. Più grande nel database può essere gestito, ma più grande in file come le immagini diventa un problema. Esistono due tipi di immagini in un sito Web:

  1. Le immagini provengono dall'amministratore per il blog dinamico. Di solito, queste immagini sono state ottimizzate prima del caricamento.

  2. Le immagini degli utenti in caso di utenti possono caricare immagini come avatar. Oppure gli utenti possono creare contenuti di blog e inserire alcune immagini dall'editor di testo. Questo tipo di immagini è difficile da prevedere la dimensione. Gli utenti possono caricare immagini di grandi dimensioni solo per contenuti di piccole dimensioni ridimensionando le dimensioni della vista ma non ridimensionandole.

Ignorando l'articolo no. 1 sopra, soluzione rapida per l'articolo n. 2 può essere temporaneamente risolto dai seguenti suggerimenti se non abbiamo funzionalità di ottimizzazione delle immagini nel nostro sito Web:

  1. Non consentire agli utenti di caricare direttamente dall'editor di testo reindirizzandoli alla galleria di immagini. In questa pagina gli utenti devono caricare il file in anticipo prima di poterlo incorporare nel contenuto. Questo metodo è chiamato come File Manager.

  2. Utilizzare una funzione di ritaglio dell'immagine per consentire agli utenti di caricare immagini. Ciò limiterà la dimensione dell'immagine anche se gli utenti caricano file molto grandi. L'immagine finale è il risultato dell'immagine ritagliata. Possiamo definire le dimensioni sul lato server e accettare solo ad esempio 500 KB o inferiore.

Ora, è solo temporaneo. Per la soluzione finale, la domanda si ripete:

  • Come gestire una grande memorizzazione di immagini?
  • Ridimensiona o modifica l'estensione.
  • In che modo un sito Web o e-commerce grande o medio gestisce l'archiviazione dei file per le loro immagini?

Cosa possiamo fare allora:

  1. Migrare dalla condivisione che ospita VPS. Non abbastanza? Quindi più in alto aggiornando a Dedicato.

  2. Crea il tuo server per l'archiviazione dei file. Googling per farlo. Questo non è così difficile come pensi. Alcune persone lo fanno per il loro sito web.

  3. Il modo più semplice è utilizzare il servizio di archiviazione dei file CDN.

Ok, 1 e 2 sono un po 'costosi. Ma n. 3 penso sia la soluzione migliore.

Alcuni servizi CDN consentono di archiviare tutti i file Web desiderati.

Domanda "come caricare file su CDN dal nostro sito Web?"

Non ti preoccupare, una volta che ti registri, di solito gratis, otterrai indicazioni su come caricare il file e ottenere il loro link da / al tuo sito web. Otterrai un'API e altro ancora. È facile.

Alcuni provider ci offrono un servizio gratuito per 14 giorni con memoria e larghezza di banda limitate. Ma andrà bene per il punto di partenza. L'unico problema è perché "le persone non ci provano mai".

Spero che possa aiutare per i principianti.


13

Abbiamo avuto clienti insistere sull'opzione B (archiviazione del database) alcune volte su alcuni back-end diversi, e alla fine siamo sempre tornati all'opzione A (archiviazione del filesystem).

BLOB di grandi dimensioni come quello non sono stati gestiti abbastanza bene nemmeno da SQL Server 2005, che è l'ultimo su cui l'abbiamo provato.

In particolare, abbiamo visto un gonfiamento grave e penso che forse i problemi di blocco.

Un'altra nota: se si utilizza l'archiviazione basata su NTFS (Windows Server, ecc.) Si potrebbe prendere in considerazione la possibilità di trovare un modo per aggirare migliaia e migliaia di file in una directory. Non sono sicuro del perché, ma a volte il file system non riesce a gestire bene quella situazione. Se qualcuno ne sapesse di più, mi piacerebbe ascoltarlo.

Ma cerco sempre di usare le sottodirectory per spezzare un po 'le cose. La data di creazione spesso funziona bene per questo:

Immagini / 2008/12/17 / .jpg

... Ciò fornisce un discreto livello di separazione e aiuta anche un po 'durante il debug. Anche i client Explorer e FTP possono soffocare un po 'quando ci sono directory davvero enormi.

EDIT: solo una breve nota per il 2017, nelle versioni più recenti di SQL Server, ci sono nuove opzioni per la gestione di molti BLOB che dovrebbero evitare gli svantaggi di cui ho discusso.

EDIT: Nota rapida per il 2020, l'archiviazione BLOB in AWS / Azure / etc è stata un'opzione per anni. Si adatta perfettamente a molti progetti basati sul Web poiché è economico e spesso può semplificare alcuni problemi relativi alla distribuzione, al ridimensionamento su più server, al debug di altri ambienti quando necessario, ecc.


4
Un buon avviso sul numero di file nella stessa directory. Può dare errori troppo difficili da trovare in un ambiente di produzione.
digao_mb,

1
Avevo già riscontrato questo problema. NTFS si è comportato in modo imprevedibile con circa 10.000 file in una cartella.
Faiz,

1
Non solo NTFS ma anche BTRFS, che ha anche un problema a gestire enormi quantità di immagini in una cartella. Vale a dire se ci provassi lsci vorrebbe un'eternità (si blocca). Oppure cancella.
sunapi386,

11

Di recente ho creato un'app PHP / MySQL che memorizza file PDF / Word in una tabella MySQL (fino a 40 MB per file finora).

Professionisti:

  • I file caricati vengono replicati sul server di backup insieme a tutto il resto, non è necessaria alcuna strategia di backup separata (tranquillità).
  • Configurare il web server è leggermente più semplice perché non ho bisogno di avere una cartella / upload e dire a tutte le mie applicazioni dove si trova.
  • Posso utilizzare le transazioni per le modifiche per migliorare l'integrità dei dati: non devo preoccuparmi di file orfani e mancanti

Contro:

  • mysqldump ora impiega molto tempo perché ci sono 500 MB di dati di file in una delle tabelle.
  • Nel complesso non è molto efficiente in termini di memoria / CPU rispetto al filesystem

Definirei la mia implementazione un successo, si occupa dei requisiti di backup e semplifica il layout del progetto. Le prestazioni vanno bene per le 20-30 persone che usano l'app.


6

Uso le immagini caricate sul mio sito Web e direi sicuramente l'opzione a).

Un'altra cosa che consiglio vivamente è quella di cambiare immediatamente il nome del file da come l'utente ha chiamato la foto, in qualcosa di più gestibile. Ad esempio qualcosa con la data e l'ora per identificare in modo univoco ogni immagine.

Aiuta anche a rimuovere il nome del file dell'utente da eventuali caratteri strani per evitare complicazioni future.


6

Ridimensiona definitivamente l'immagine e controlla il formato se puoi. Ci sono stati casi di file dannosi caricati e serviti da host inconsapevoli, ad esempio la vulnerabilità GIFAR ti ha permesso di nascondere un'applet java dannosa in un file GIF, che sarebbe quindi in grado di leggere i cookie nel contesto corrente e inviarli a un altro sito per un attacco di scripting cross-site. Il ridimensionamento delle immagini di solito impedisce questo, in quanto muta il codice incorporato. Mentre questo attacco è stato risolto dalle patch JVM, la pubblicazione ingenua di file binari senza scrub li apre a tutta una serie di vulnerabilità.

Ricorda, la maggior parte degli scanner antivirus può essere eseguita solo sul filesystem: se memorizzi i tuoi binari nel DB, non sarai in grado di eseguire uno scanner contro di loro molto facilmente.


4

Esiste una sorta di approccio ibrido in SQL Server 2008 chiamato il tipo di dati filestream di cui si è parlato su RunAs Radio # 74 , che è un po 'come il migliore di entrambi i mondi. Molte persone non hanno l'otione del 2008, ma se lo fai, questa opzione sembra piuttosto interessante


4

Questo è fondamentalmente lo faccio.

  1. Memorizza un'immagine caricata in una directory o memoria temporanea.
  2. Elabora quell'immagine prima di memorizzarla permanentemente. 2.1. Correzioni del colore 2.2. Comprimi 2.3. Creare più copie in base alle dimensioni dell'immagine 2.4. Rinomina con i suffissi .xl, .lg, .md, .sm ecc
  3. Comprime tutti i file di immagine elaborati (da un singolo file) all'interno di una cartella con il nome della cartella in quanto idverranno archiviati nel database per qualsiasi riga / documento insieme image file name(o potrebbe essere un nome casuale come nome dell'immagine).
  4. Crea cartella yyyy / mm / d path se non esiste. Ad esempio il 21/08/2016. Ricorda quel percorso e memorizza nel database per lo stesso documento e riga.
  5. Sposta la idcartella delle immagini nella pathcartella. (La cartella Path può trovarsi nella cartella / var / web-content.)
  6. Svuota il buffer di memoria o elimina il file temporaneo.

Quando devi accedere a qualsiasi immagine menzionata in un documento, hai il percorso e l'id della cartella che contiene le immagini. Per esempio/var/web-content/{{path}}/{{id}}/image-file-name.sm.jpg

In questo modo se devi eliminare tutti i file di immagine elaborati, elimina semplicemente la cartella e il suo contenuto in modo ricorsivo.


3

Molte implementazioni sono l'opzione A.

Con l'opzione B, apri un'intera grande lattina di whoop4ss quando esegui il marshalling di quei bit dal database in qualcosa che può essere visualizzato su un browser ... Inoltre, se il db è inattivo, le immagini non sono disponibili.

Non credo che lo spazio sia troppo problematico ... Le unità Terabyte sono un paio di centinaia di dollari ora.

Stiamo implementando con l'opzione A perché non abbiamo il tempo o le risorse per fare l'opzione B.


3

Per il ridimensionamento automatico, prova imagemagick ... è usato per molti dei principali sistemi di gestione di contenuti / foto open source ... e credo che ci siano alcune estensioni .net per esso.


2

Usiamo A. Lo metterei su un'unità condivisa (a meno che tu non abbia intenzione di eseguire più di un server).

Se arriva il momento in cui ciò non si ridimensiona, è possibile esaminare i meccanismi di memorizzazione nella cache.


2

Assolutamente, positivamente l'opzione A. Altri hanno menzionato che i database in genere non gestiscono bene i BLOB, indipendentemente dal fatto che siano progettati per farlo o meno. I filesystem, d'altra parte, vivono per queste cose. Hai la possibilità di utilizzare lo striping RAID, la diffusione di immagini su più unità, persino la loro diffusione su server geograficamente disparati.

Un altro vantaggio è che i backup / replica del database sarebbero mostruosi.



2

Per motivi di sicurezza, è anche consigliabile evitare i problemi causati dallo sniffing dei contenuti di IE che può consentire agli aggressori di caricare JavaScript all'interno di file di immagini, che potrebbero essere eseguiti nel contesto del tuo sito. Quindi potresti voler trasformare le immagini (ritagliarle / ridimensionarle) in qualche modo prima di memorizzarle per prevenire questo tipo di attacco. Questa risposta ha alcune altre idee.


2

Bene, ho un progetto simile in cui gli utenti caricano i file sul server. Dal mio punto di vista, l'opzione a) è la migliore soluzione grazie alla sua maggiore flessibilità. Quello che devi fare è archiviare le immagini in una cartella protetta classificata per sottodirectory. La directory principale deve essere impostata dall'amministratore in quanto il contenuto non deve eseguire script (molto importanti) e (leggere, scrivere) protetti per non essere accessibili nella richiesta http.

Spero che questo ti aiuta.


1

Se sono piccoli file che non dovranno essere modificati, l'opzione B non è una cattiva opzione. Preferisco questo alla scrittura della logica per archiviare i file e gestire i pazzi problemi della struttura delle directory. Avere molti file in una directory è male. emkay?

Se i file sono di grandi dimensioni o richiedono una modifica costante, specialmente da programmi come Office, l'opzione A è la soluzione migliore.

Nella maggior parte dei casi, è una questione di preferenza, ma se si passa all'opzione A, assicurarsi che le directory non contengano troppi file. Se si sceglie l'opzione B, fare in modo che la tabella con i dati BLOB sia nel proprio database e / o gruppo di file. Ciò contribuirà alla manutenzione, in particolare backup / ripristini. I tuoi dati regolari sono probabilmente abbastanza piccoli, mentre i dati delle immagini saranno enormi nel tempo.


1

Dipende dalle tue esigenze, in particolare volume, utenti e frequenza di ricerca. Ma, per gli uffici di piccole o medie dimensioni, l'opzione migliore è utilizzare un'applicazione come Apple Photos o Adobe Lighroom. Sono specializzati per archiviare, catalogare, indicizzare e organizzare questo tipo di risorsa. Tuttavia, per le grandi organizzazioni, con forti requisiti di archiviazione e un elevato numero di utenti, si consiglia di creare un'istanza di una piattaforma di gestione dei contenuti con una gestione delle risorse digitali, come Nuxeo o Alfresco; entrambe offrono ottime risorse per gestire enormi volumi di dati con metodi semplificati per recuperarli. E, molto importante: esiste un'opzione gratuita (open source) per entrambe le piattaforme.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.