Search code examples
ruby-on-railsgoogle-cloud-storagecarrierwavesendfile

Send_data returning corrupted files


I have the following download action in my resources controller:

def download
    require 'open-uri'

    if validate_token(safe_params[:x])
        resource = Resource.find_by_token(safe_params[:x])
        data = open(resource.file.url)

        send_data( data, :disposition => 'attachment',:url_based_filename => true, type: data.meta['content-type'].to_s)
        #  send_file data, disposition: 'attachment'
        # redirect_to resource.file.url
        puts data.hash
        puts data.meta['x-goog-hash']
    else
        redirect_to pages_error_path, notice: 'Does not match resource.'

    end
end

The action downloads a file stored on Google Storage (using carrierwave) and then streams that file to the browser. I tried multiple different configurations of the parameters to send_data and I tried send_file as well. The closest I have come to a working solution is where a PDF file is downloaded but it is corrupt. (Sometimes it accidentally downloads a text document, and rather than the expected file contents I get the memory object of the file as shown below.

#<File:0x007fcdda128ea0>

I have a feeling the same happens with the PDF download, except that the PDF viewer obviously cannot render that PDF.

I made sure that the URL stored in the database does point to the correct file and the data variable is initialized correctly. Everything works as expected up until the point where the data is sent to the browser.

The reason I do this rather than redirecting to the file url is because i dont want to expose the file location on Google storage to the user (hence the temporary download to the server)


Solution

  • send_data data.read, disposition: 'attachment', stream: 'true', buffer_size: '4096'
    

    Add in stream: true