Reputation: 6381
I have paperclip (with S3) working in my application, for audio files. The model definition connects S3 with paperclip.
# attachments
has_attached_file :audio, storage: :s3, s3_credentials: Proc.new{|a| a.instance.s3_credentials}
validates_attachment_content_type :audio, :content_type => [ 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/mpeg3', 'audio/x-mpeg3', 'audio/mpg', 'audio/x-mpg', 'audio/x-mpegaudio' ]
I can upload the files via a rails simple_form, using this code:
<%= simple_form_for(@sentence) do |f| %>
<%= f.error_notification %>
.
<%= f.input :audio, as: :file %>
.
<% end %>
I would also like to create audio using a background (Resque) process. This code retrieves an audio stream from a web API and attempts to save it to the existing model instance. It does not work.
sentences.each do |sentence|
sentence.audio = get_audio(sentence.sentence)
sentence.save
end
Paperclip doesn't seem to know how to handle the audio stream.
failed: #<Paperclip::AdapterRegistry::NoHandlerError: No handler found for "\xFF\xF3\xC8\xC4\x00\x00\x00\x03H\x00\x00\x00\x00LAME3.99.5\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
** PROGRESS **
I made some progress: wrote the audio stream to an Tempfile... but now Paperclip is complaining about encoding
def get_audio_tempfile(target)
audio = translator.speak "#{target}", :language => "#{@language_cd}", :format => 'audio/mp3', :options => 'MaxQuality'
tempfile = Tempfile.new("target_temp.mp3")
tempfile.binmode
tempfile.write(audio)
tempfile.close
tempfile.open
tempfile
end
Error:
[paperclip] Content Type Spoof: Filename target_temp.mp320160226-32064- r391y9 (audio/mpeg from Headers, [] from Extension), content type discovered from file command: audio/mpeg. See documentation to allow this combination.
Upvotes: 2
Views: 162
Reputation: 6381
A summary of how to save an audio stream to Paperclip / S3 without going via the view.
Assuming Paperclip is working and writing to S3, the following steps are needed to upload a file (using Paperclip) from somewhere else than the view (in my case, it is a Resque process).
Why do this: to allow for a fix of foreground and background processing, or to batch upload a lot of data.
model
# attachments
has_attached_file :audio, storage: :s3, s3_credentials: Proc.new{|a| a.instance.s3_credentials}
validates_attachment_content_type :audio, :content_type => [ 'audio/mpeg', 'audio/x-mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/mpeg3', 'audio/x-mpeg3', 'audio/mpg', 'audio/x-mpg', 'audio/x-mpegaudio' ]
view
<%= simple_form_for(@sentence) do |f| %>
<%= f.error_notification %>
.
<%= f.input :audio, as: :file %>
.
<% end %>
job
sentence.audio = get_audio_tempfile(sentence.sentence)
sentence.save
get_audio_tempfile
def get_audio_tempfile(target)
audio = translator.speak "#{target}", :language => "#{@language_cd}", :format => 'audio/mp3', :options => 'MaxQuality'
tempfile = Tempfile.new(['target_temp','.mp3'])
tempfile.binmode
tempfile.write(audio)
tempfile.rewind
tempfile
end
Important notes:
Thank you to @tobmatth for the help with the file issues.
Upvotes: 0
Reputation: 269
I don't get what exactly your get_audio method is doing, but you need to make sure it returns a file handle, e.g.
sentence.audio = File.new(path_to_your_file, "r")
sentence.save
As for your Tempfile approach, make sure to create it like this
Tempfile.new([ 'foobar', '.mp3' ])
This way PaperClip won't complain about the file extension
Upvotes: 1