2012-05-08 9 views
19

Recupero le immagini con open-uri da un sito Web remoto e le conservo sul mio server locale all'interno dell'applicazione Ruby on Rails. La maggior parte delle immagini sono state mostrate senza problemi, ma alcune immagini non si sono mostrate.Perché OpenURI considera i file con dimensioni inferiori a 10kb come StringIO?

Dopo un lunghissimo debug-sessione ho finalmente scoperto (grazie a this blogpost) che la ragione di questo è che il class Buffer nei file open-uri-libary Tratta con meno di 10KB di dimensioni come IO-oggetti anziché ai file temporanei.

sono riuscito a aggirare questo problema seguendo la risposta da Micah Winkelspecht a this StackOverflow question, dove ho messo il seguente codice all'interno di un file nei miei inizializzatori:

require 'open-uri' 
# Don't allow downloaded files to be created as StringIO. Force a tempfile to be created. 
OpenURI::Buffer.send :remove_const, 'StringMax' if OpenURI::Buffer.const_defined?('StringMax') 
OpenURI::Buffer.const_set 'StringMax', 0 

Questo funziona come previsto finora, ma io continua a chiedersi, perché hanno messo questo codice nella libreria, in primo luogo? Qualcuno conosce un motivo specifico, , perché i file di dimensioni inferiori a 10 KB sono trattati come StringIO?

Poiché il codice sopra riportato praticamente resetta questo comportamento a livello globale per tutta la mia applicazione, voglio solo assicurarmi di non infrangere nient'altro.

risposta

12

Quando si esegue la programmazione di rete, si assegna un buffer di dimensioni ragionevolmente grandi e si inviano e leggono unità di dati che si adatteranno nel buffer. Tuttavia, quando si tratta di file (o talvolta di cose chiamate BLOB) non si può presumere che i dati si adattino al proprio buffer. Quindi, è necessario un trattamento speciale per questi grandi flussi di dati.

(A volte le unità di dati che si adattano al buffer si chiamano pacchetti.Tuttavia, i pacchetti sono in realtà una cosa di livello 4, come i frame sono al livello 2. Poiché questo sta accadendo a un livello 7, potrebbero essere meglio chiamati messaggi .)

Per le risposte superiori a 10 K, la libreria open-uri sta configurando l'overhead aggiuntivo per scrivere su oggetti di flusso. Quando è sotto la dimensione StringMax, include solo la stringa nel messaggio, poiché sa che può adattarsi al buffer.

+0

grazie, bella spiegazione – klaffenboeck

+3

Non proprio corretto. La stringa utilizzata come buffer in questo caso non ha una dimensione fissa; le stringhe in Ruby vengono ridimensionate dinamicamente. In effetti, è possibile ridimensionare i buffer in modo dinamico nella maggior parte delle lingue (anche se non sempre automaticamente). Sospetto che il vero motivo dell'uso di StringIO per i file di piccole dimensioni sia un compromesso tra prestazioni e memoria. – pelle

+2

Vero @pelle. Notando che hai detto non abbastanza. Nel caso di BLOB, * qualsiasi * supposizione sull'adattamento potrebbe essere interrotta da un BLOB ancora più grande. Ciò include ciò che non si adatta alla memoria. A un certo punto, la gestione degli stream richiede lo streaming e la classe Buffer sceglie 10K come punto di svolta per abbandonare e gestire il file tramite lo streaming. –

Problemi correlati