Question

I am in a strange situation where send_file is unable to send file correctly. Here is situation:

Rail version: 3.0.10 and 3.1.0 [two different branches for testing] Ruby: 1.9.2 on RVM Webserver: Apache with Passenger

My client has a document management system; I worked on upgrading it to Rails 3 (and now rails 3.1) from Rails 2. We mostly redeveloped the system as the earlier one was quite old. All the features are working except one. The application allows users to download documents assigned to them. When users login they can see which documents are assigned to them and they can download. It works perfectly fine. Here is the code which works:

send_file(document.file[:path],
                    :type => document.file[:content_type],:x_sendfile=>true, :filename=>document.name)

There is one client for which they (my client) have made their earlier solution to send the document when requested through a .NET based web service (or whatever it may be called). The web service authenticates as a user and then is forwarded to document download path. I am able to make the web service authenticate and then redirect to the controller action which downloads the files but it does not work. The Server log says everything is ok:

Started GET "/download/12234" for 12.123.12.123 at 2011-09-20 23:21:24 -0400
  Processing by DocumentController#download as HTML
  Parameters: {"id"=>"12234"}
Sent file /yyy/zzz/abc/12234 (0.1ms)
Completed 200 OK in 138ms

I have changed the specific names and IPs. Note that the IP (12.123.12.123) is for the server which hosts web service.

I was on call with the developer who developed the .NET web service and he says he getting all the headers correct except that the content length is -1 and he is receiving no content. He said all other headers are correct.

To solve the problem; I tried multiple variations of send_file by trying to set all possible options (x_sendfile, stream, disposition etc).. I also tried setting the header:

response.headers["Cache-Control"] = "no-cache, no-store, max-age=0, must-revalidate"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"

But nothing works when I use the web service to download the file. However, same method works directly in the browser [I tested by bypassing authentication in the code].

I tried using send_date, but it does not work:

File.open(document.file[:path], 'r') do |f|
send_data f.read, :type => document.file[:content_type], :filename => document.name, :disposition => 'inline'
end

As a workaround I tried redirect_to instead of send file and used a test file in the public folder and it works. Although insecure but this seems to work fine. The only problem is that the browser is now opening the document instead of downloading it.

Please help me.

Update: The problem was related to the fact that Rails now sends chunked content and the web service was expecting content length.

Était-ce utile?

La solution

It was not a problem with send_file. It was how the .NET web service was programmed. It was expecting content length.

There is a change (between Rails 2 & Rails3) in the default behaviour when sending content. Now it is chunked content - so there can not be a content length.

The .NET guy changed the code and everything is now working fine! Hope this would help somebody.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top