Converti i nomi dei file nel loro checksum prima di salvare per evitare duplicati. È una cosa intelligente da fare?

5

TL; DR: cosa dice il titolo

Sto sviluppando una sorta di scheda immagine in PHP. Stavo pensando di cambiare il nome di ogni immagine con il checksum prima di salvarlo. In questo modo, potrei essere in grado di prevenire i duplicati.
So che questo non funzionerebbe per due immagini uguali ma diverse per dimensioni o livello di compressione o quant'altro, ma questo metodo consentirebbe un controllo anticipato.
Quello che mi infastidisce è che non ho mai visto questo metodo implementato da nessuna parte, quindi mi chiedevo se c'è un problema. Forse è solo più efficiente mantenere il nome file originale e archiviare l'hash nel DB? Forse l'intero metodo non è utile e la mia domanda è discutibile?
Cosa ne pensi?

Da una nota a margine, non capisco come vengono calcolati gli hash, quindi mi stavo chiedendo, se viene esaminata la mia prima domanda, se sarebbe possibile calcolare la somiglianza di due immagini simile confrontando gli hash (levenshtein o qualcosa del genere).

    
posta Xananax 25.06.2011 - 03:10
fonte

4 risposte

5

Un hash seminato con qualcosa di statico (come il nome di un file o il file reale) ti dirà se c'è una corrispondenza esatta, ma non ti aiuterà con somiglianza, poiché gli hash divergeranno significativamente anche con modifiche minori. Quindi hai due opzioni:

1. Ignora il problema ...

... e assicurati solo che i file non entrino in collisione tra loro, anche se sono duplicati (il più veloce).

Questo è il punto in cui gli hash diventano utili: seminare un hash con qualcosa di relativamente unico garantisce virtualmente la possibilità di fare riferimento univocamente a un file, anche se il suo nome file è uguale o l'immagine è simile. Il valore di questo, specialmente in una scheda immagine, è per i CDN: la maggior parte dei CDN generalmente determina i duplicati in base al nome del file (perché è veloce). Quindi se qualcuno apporta una modifica a un'immagine ma usa lo stesso nome di file, la CDN ignorerà la nuova versione.

Quindi, se il tuo nome file è foo.jpg , potresti creare un hash usando qualcosa come

list(basename, extension) = split(filename, '.')
hash = md5(filename . ':' . time())
filename = basename . '_' . hash . extension

E arriva a qualcosa come foo_a23aed3a298ae.jpg . Poiché il nome base e l'estensione non cambiano, sarebbe banale generare il nome del file originale.

Inoltre, poiché l'hash è stato seminato con il tempo, dovresti avere un hash per lo più unico, anche quando i due file sono per lo più gli stessi.

2. Calcola i criteri di somiglianza delle immagini una volta ...

... e memorizza i risultati nei metadati dell'immagine o in un database separato (più lento, ma con maggiori possibilità di salvataggio).

Questo andrebbe di pari passo con la prima opzione.

Qualsiasi buona libreria di immagini fornirà una grande quantità di dati su un'immagine che è possibile utilizzare per creare una formula di confronto tra due immagini. Quindi memorizzerai quei dati nell'immagine stessa (accessibili tramite metadati come EXIF o IPTC) o in un database a cui fa riferimento l'hash univoco dell'immagine.

Naturalmente, in questo scenario, stai cercando nel database tutte le corrispondenze. Potresti risparmiare un po 'di tempo aggiungendo i metadati importanti al nome del file:

foo_200x200_300dpi_cats_a23aed3a298ae.jpg

Tuttavia, a seconda della quantità di immagini che devi ordinare, questo può essere molto costoso e probabilmente supererebbe il costo dello spazio di archiviazione aggiuntivo.

    
risposta data 25.06.2011 - 03:19
fonte
4

Git memorizza i file (e anche altre cose) indicizzati dagli hash SHA-1, che sono un po 'più lunghi e più a prova di collisione rispetto al semplice checksum. Con un hash crittografico, dovresti anche essere in grado di troncare il valore hash e ciò che rimane dovrebbe funzionare come hash di lunghezza ridotta.

    
risposta data 25.06.2011 - 04:43
fonte
1

È importante sapere che gli hash e i checksum sono calcolati in modo che piccole differenze nell'input risultino in un hash completamente non correlato. Ha un grande valore nella valutazione dei duplicati esatti, ma non può essere utilizzato per calcolare la somiglianza. (Per questo, la compressione e gli algoritmi di somiglianza esplicita sono probabilmente più utili, ma non posso aiutarti molto con quello.)

Oltre a questo, usare gli hash come nomi di file è sicuramente una possibilità, e ho visto che è stato implementato. Il motivo per cui non viene visto più spesso è probabilmente perché molti sistemi (specialmente le web app) ricorrono all'archiviazione dei dati attraverso il database, che è anche una possibilità molto reale, specialmente se ci sono comunque altre informazioni che è necessario memorizzare in un database. (È possibile memorizzare il binario in un BLOB e avere altre colonne per indicare il nome e altre proprietà.) Poiché i database hanno una buona gestione delle chiavi univoca, l'hash non è necessario (anche se può ancora essere utilizzato per trovare duplicati esatti, solo memorizza l'hash con il binario.)

Se stai utilizzando il file system, ci sono due aspetti positivi aggiuntivi nell'utilizzo degli hash:

  1. assicura che le immagini che non sono le stesse hanno nomi di file diversi (con l'avvertenza di collisioni di hash ovviamente), quindi non avrai% di% di% di tutto il posto.
  2. assicura che non c'è possibilità di sconvolgere il filesystem con caratteri insoliti o la lunghezza del nome del file in eccesso o qualsiasi altra cosa
risposta data 25.06.2011 - 09:25
fonte
0

Per il tipo di applicazione che descrivi, ne vale la pena. Ma tu vuoi presentare i file agli utenti con il nome originale, non il checksum o l'hash del nome del file, se hai intenzione di presentare i nomi dei file agli utenti.

    
risposta data 25.06.2011 - 06:45
fonte

Leggi altre domande sui tag