Reputation: 1105
I am working on a Ruby on Rails 4 project that has been deployed to Heroku. Basically, a user needs to have the ability to upload and download sound files. Uploading a file was fairly straight forward. However, downloading has been strangely difficult. I have found several posts on Stack Overflow that have been helpful, but I still need help.
In config/environments/production.rb:
config.paperclip_defaults = {
:storage => :s3,
:s3_protocol => 'http',
:s3_credentials => {
:bucket => ENV['S3_BUCKET_NAME'],
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
My model:
class Sound < ActiveRecord::Base
belongs_to :user
# for paperclip
has_attached_file :sound_file,
:s3_domain_url => "bucketname.s3.amazonaws.com",
:bucket => 'bucketname',
:s3_permissions => :public_read,
:encode => 'utf8'
# do not create a sound unless a sound file
# is present
validates_attachment_presence :sound_file
end
When the user clicks on this, a file should be downloaded:
<%= button_to "Download", download_url(sound.id), :method => :get %>
My controller:
def download
@sound= Sound.find(params[:id])
data = open(@sound.sound_file)
send_data data.read, :type => data.content_type, :x_sendfile => true
end
When I look at the logs from heroku, I see this error message:
Parameters: {"id"=>"5"}
Started GET "/sounds/5/download" for 76.168.22.71 at 2013-11-16 01:22:17 +0000
Processing by SoundsController#download as HTML
Started GET "/sounds/5/download" for 76.168.22.71 at 2013-11-16 01:22:17 +0000
Parameters: {"id"=>"5"}
Processing by SoundsController#download as HTML
Completed 500 Internal Server Error in 6ms
Completed 500 Internal Server Error in 6ms
app/controllers/sounds_controller.rb:40:in `download'
app/controllers/sounds_controller.rb:40:in `download'
TypeError (no implicit conversion of Paperclip::Attachment into String):
TypeError (no implicit conversion of Paperclip::Attachment into String):
Any idea what I am doing wrong?
Upvotes: 2
Views: 837
Reputation: 1105
Solved this! Here is the download function I used in my controller.
def download
@sound= Sound.find(params[:id])
send_file Paperclip.io_adapters.for(@sound.sound_file).path,
:filename => @sound.sound_file_file_name,
:type => @sound.sound_file_content_type,
:disposition => 'attachment',
:x_sendfile => true
end
Upvotes: 1
Reputation: 1105
So....I partially solved the issue:
def download
@sound= Sound.find(params[:id])
send_data @sound.sound_file, :disposition => 'attachment', :x_sendfile => true
end
This does cause a file download, but the downloaded file is a text document with the following written inside:
http://s3.amazonaws.com/bucketname/sounds/sound_files/000/000/005/original/83746__braffe2__pen-writing.wav?1384493473
The good news is that Paperclip seems to be able to find the file. The bad news is that it is just returning a text document instead of a .wav file. Any hints?
UPDATE
Replaced send_data with send file in the controller:
def download
@sound= Sound.find(params[:id])
send_file @sound.sound_file.url,
:filename => @sound.sound_file_file_name,
:type => @sound.sound_file_content_type,
:disposition => 'attachment',
:x_sendfile => true
end
Now when I try to download from the app on Heroku, I get this error message:
Sent file http://s3.amazonaws.com/bucketname/sounds/sound_files/000/000/005/original/83746__braffe2__pen-writing.wav?1384493473 (0.2ms)
Sent file http://s3.amazonaws.com/bucketname/sounds/sound_files/000/000/005/original/83746__braffe2__pen-writing.wav?1384493473 (0.2ms)
ActionController::MissingFile (Cannot read file http://s3.amazonaws.com/bucketname/sounds/sound_files/000/000/005/original/83746__braffe2__pen-writing.wav?1384493473):
app/controllers/sounds_controller.rb:40:in `download'
I am pretty sure I am almost there. Any hints? One question I have is what are all of those numbers after '?' in the file path?
Upvotes: 2