2011-02-27 14 views
24

Así que esto debería ser bastante fácil, pero no puedo hacer que funcione.Renderizar una imagen

Tengo un método de controlador que encuentra una imagen basada en una consulta, luego la salida se almacena en caché. La imagen podría ser remota (flickr, google images, etc.) o podría ser local. Independientemente de la fuente, solo necesito tomar los contenidos del archivo de imagen y pasarlo al usuario. En esencia, un proxy. Pasar por imágenes remotas parece funcionar bien, pero al pasar a través de imágenes locales me da una:

invalid byte sequence in UTF-8 

Así que esto es lo que obtuve. Espero que alguien pueda resolver el problema o guiarme en una mejor dirección con mi código.

def image_proxy 
    query = params[:query] 
    image_url = get_image_url(query) # returns an absolute local file path or a URL 

    response.headers['Cache-Control'] = "public, max-age=#{12.hours.to_i}" 
    response.headers['Content-Type'] = 'image/jpeg' 
    response.headers['Content-Disposition'] = 'inline' 
    render :text => open(image_url).read 
end 

archivos remotos funcionan bien, los archivos locales no lo hacen.

bonificación a cualquier persona que pueda ayudar a resolver este otro tema:

  1. necesito para establecer el tipo de contenido adecuado. Las URL de imagen remotas no me dicen el tipo de imagen, solo obtengo una url y, a veces, la url no contiene una extensión. Así que elegí jpeg porque parece funcionar independientemente del tipo de imagen que me envíe.

¡Gracias!

Respuesta

23

Pruebe usar render :text => open(image_url, "rb").read, que le dice a Ruby que el archivo que abre es binario, y que no intente leerlo como texto.

edición

Para la pregunta extra, se podía leer los primeros bytes y ver lo que contienen. Un PNG siempre comenzará con los valores de bytes hexadecimales 89 50 4E 47 0D 0A 1A 0A (o los valores decimales 137 80 78 71 13 10 26 10).

Wikipedia tiene un list of magic numbers used to identify file que puede ver. Simplemente cree un método de algún tipo que lea los primeros bytes y lo compare con eso.

+0

Gran respuesta, funcionó a la perfección. –

14

¿Qué versión de Rails? Para Rails 3, debe mirar el streaming methods que se agregaron. send_data sería la forma correcta de enviar datos binarios. Si las imágenes son locales y su servidor web lo admite, puede usar send_file, que no bloqueará una instancia de raíles mientras el usuario descarga una imagen.

+1

Sí, 'send_data' es lo que quiere, no' render'. – aceofspades

Cuestiones relacionadas