Recojo imágenes con open-uri desde un sitio web remoto y las conservo en mi servidor local dentro de mi aplicación Ruby on Rails. La mayoría de las imágenes se mostraron sin problemas, pero algunas imágenes simplemente no aparecieron.¿Por qué OpenURI trata los archivos de menos de 10kb como StringIO?
Después de una larga sesión de depuración a fin descubrí (gracias a this blogpost) que la razón de esto es que el class Buffer
en los archivos open-uri-libary trata con menos de 10 kb de tamaño a medida IO-objetos en lugar de TEMPFILES.
me las arreglé para conseguir alrededor de este problema siguiendo la respuesta de Miqueas Winkelspecht a this StackOverflow question, donde pongo el siguiente código dentro de un archivo en mis inicializadores:
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
Esto funciona como se esperaba hasta ahora, pero yo sigan preguntándose, ¿por qué pusieron este código en la biblioteca en primer lugar? ¿Alguien sabe un motivo específico, por qué los archivos de menos de 10kb se tratan como StringIO?
Dado que el código anterior prácticamente restablece este comportamiento globalmente para toda mi aplicación, solo quiero asegurarme de no romper nada más.
gracias, buena explicación – klaffenboeck
No del todo correcto. La cadena que se usa como buffer en este caso no tiene un tamaño fijo; las cadenas en Ruby se cambian de tamaño dinámicamente. De hecho, puede cambiar el tamaño de los búferes de forma dinámica en la mayoría de los idiomas (aunque no siempre de forma automática). Sospecho que la verdadera razón para usar StringIO para archivos pequeños es una compensación de uso de rendimiento/memoria. – pelle
True @pelle. Tomando nota de que dijiste que no del todo. En el caso de los BLOB, * cualquier * suposición sobre el ajuste podría romperse con un BLOB aún mayor. Eso incluye lo que no cabe en la memoria. En algún punto, el manejo de flujos requiere transmisión, y la clase Buffer está eligiendo 10K como el punto de inflexión para simplemente abandonar y manejar el archivo mediante transmisión. –