Sending a file *and* rendering a page

Anyone know how to send a file/data to the user agent (download it)
using #send_file or #send_data, and render a new page in the same
action?

This just sends the file and doesn’t render the page:
def gimme

send_data(our_data, :filename => ‘output.csv’, :disposition =>
‘attachment’)
end

And this will give a Double-Render error:

def gimme

send_data(our_data, :filename => ‘output.csv’, :disposition =>
‘attachment’)
render :action => :gimme
end

As will a redirect. Hopefully I’m missing a really obvious solution
here.

Any ideas? Thanks.

Anyone know how to send a file/data to the user agent (download it)
using #send_file or #send_data, and render a new page in the same
action?

Render the page and at the top of the page put something like this:

Just make sure that gets into your page before the closing .

-philip

that checks for a double-render…)
Because HTTP is a stateless request/response protocol. One request. One
response. You’re trying to respond with two things :slight_smile:

You could wrap this up in a helper/plugin to hide what’s going on, but
this is still going to be the end result :slight_smile:

-philip

Philip H. wrote:

Anyone know how to send a file/data to the user agent (download it)
using #send_file or #send_data, and render a new page in the same
action?

Render the page and at the top of the page put something like this:

Just make sure that gets into your page before the closing .

-philip

Thanks! That works fine. Not exactly elegant or very Rails-like, but it
works!

I’m still open to other ideas, but at least this gets me going again.

Anyone know if there’s a (real) reason why you can’t send a file/data
and render a page using the common Rails methods? (Besides the fact that
someone early on forgot about this possibility when creating the code
that checks for a double-render…)

/kian

Philip H. wrote:

that checks for a double-render…)
Because HTTP is a stateless request/response protocol. One request. One
response. You’re trying to respond with two things :slight_smile:

You could wrap this up in a helper/plugin to hide what’s going on, but
this is still going to be the end result :slight_smile:

-philip

Yeah. Oh well.

Since I’ve really got data that I want to send (rather than a file), and
I don’t want to create a temporary file from it, I instead put it into
the flash. The new URL in the META tag is a controller action that pulls
the data out of flash.now and uses #send_data to create the response.
Works well, except for the ugliness of putting that meta tag in the
layout for this view only…

Since I’ve really got data that I want to send (rather than a file), and
I don’t want to create a temporary file from it, I instead put it into
the flash. The new URL in the META tag is a controller action that pulls
the data out of flash.now and uses #send_data to create the response.
Works well, except for the ugliness of putting that meta tag in the
layout for this view only…

Change your layout to include this at the top (in the tag):

<%= yield “page_header” %>

Then in your view do this:

<% content_for(“page_header”) do -%>

<% end -%>

That’s what we do. And you’ll find other uses for it too… like having
a
yield block for javascript that has to go at the bottom of the page
just
before the closing because IE can’t deal with it in the middle,
etc…

-philip

Philip H. <rails@…> writes:

Anyone know how to send a file/data to the user agent (download it)
using #send_file or #send_data, and render a new page in the same
action?

Render the page and at the top of the page put something like this:

Meta http-equiv tags are a bit redundant in a web application where you
can set
the headers yourself (hint: http-equiv = ‘equivalent to an HTTP header’)

http-equiv was designed for environments where authors didn’t have
access to
changing the headers (i.e. uploading a static HTML page), and was a
nasty hack
even back then. Sending the correect header is definitely nicer.

Anyone know how to send a file/data to the user agent (download it)
using #send_file or #send_data, and render a new page in the same
action?

Render the page and at the top of the page put something like this:

Meta http-equiv tags are a bit redundant in a web application where you can set
the headers yourself (hint: http-equiv = ‘equivalent to an HTTP header’)

Good point. But if you need to cache that page then this wouldn’t
work…