21

in my rails app, I need to pass back a image.

I have a 1x1.gif tracking pixel in my route as follows:

 match "/_ctrack.gif" => "email_tracking_pixels#my_method"

In the controller:

def my_method
    send_data open('https://www.xxxxxx.com/images/1x1_transparent.gif') {|f| f.read }, :filename => '1x1_transparent.gif', :type => 'image/gif'
end

The problem is that for some reason sometimes this times outs. with the following error:

2011-03-07T20:08:36-08:00 heroku[router]: Error H12 (Request timeout) -> GET www.xxxxxxx.com/images/1x1_transparent.gif dyno=web.1 queue=0 wait=0ms service=0ms bytes=0
2011-03-07T20:08:36-08:00 app[web.1]: 
2011-03-07T20:08:36-08:00 app[web.1]: OpenURI::HTTPError (503 Service Unavailable):
2011-03-07T20:08:36-08:00 app[web.1]:   app/controllers/email_tracking_pixels_controller.rb:19:in `my_method'
2011-03-07T20:08:36-08:00 app[web.1]:   lib/rack/www.rb:7:in `call'

Any ideas on how I can pass this image that's stored locally, versus having to use open and make a web call back to my own server?

Thanks

AnApprentice
  • 108,152
  • 195
  • 629
  • 1,012

2 Answers2

50

Wouldn't be better to use send_file instead?

send_file Rails.root.join("public", "file.gif"), type: "image/gif", disposition: "inline"
David Morales
  • 17,816
  • 12
  • 77
  • 105
  • 2
    `send_file` would be a much better alternative and can take advantage of X-SendFile or X-Accel-Redirect headers in your web server to avoid tying up a ruby process. – adamcooke Mar 18 '12 at 20:50
  • This provides much better behavior on the client side. – Dogweather Apr 05 '13 at 03:19
17

Is there a reason that you cannot save the file to public/_ctrack.gif, remove the route, and let the underlying web server serve the image?

If you need to process the image from disk, just use open on the local filename:

send_data open("#{Rails.root}/path/to/file.gif", "rb") { |f| f.read } .......

The rb sets the file to open and binary modes.

Michelle Tilley
  • 157,729
  • 40
  • 374
  • 311
  • I didn't know open could do that. – AnApprentice Mar 08 '11 at 04:29
  • I haven't tested it, but this may work too, doesn't require a block, and closes the file when done: `send_data File.read("/path/to/file", :mode => "rb"), :filename => '1x1_transparent.gif', :type => 'image/gif'` – Michelle Tilley Mar 08 '11 at 04:39