Ruby on Rails: descargar archivos desde Amazon S3

Con el trabajo, clases y entrenamientos (si también practico deportes), no puedo escribir tanto como quisiera, pero vamos haciendo la lucha.

Caso de estudio:

  • Aplicación alojada en Heroku, por tanto no se pueden subir archivos al servidor, se tienen que subir a Amazon S3.
  • Para subir los archivos se uso CarrierWave.
  • Se desea descargar los archivos alojados en Amazon S3 desde la aplicación en cuestión.

Vamos primero, instalando la gema necesaria, en el archivo Gemfile:

gem 'aws-s3'

Luego el bundle:

bundle install

En app/config/initializers se crea un archivo, en este caso aws_credentials.rb, con el siguiente contenido:

AWS::S3::Base.establish_connection!(
 :access_key_id => 'your_key_id',
 :secret_access_key => 'your_secret_key'
)

Suponiendo que se tiene un controlador files_controller.rb, y un modelo file.rb, se agregala función en cuestion para descargar el archivo

def download
 file = Files.find(params[:id])
 filename = file.filename.to_s.split('?').first.split('/').last
 aws_path = 'uploads/' + filename
 aws_object = AWS::S3::S3Object.find aws_path, 'bucket'
 send_data(aws_object.value, :filename => filename,:disposition => 'attachment') 
end

Debido a CarrierWave, file.filename, devuelve toda la url del archivo alojado en Amazon S3, es por que se esta usando el split, para obtener solo el nombre del archivo y almacenarlo en la variable filename.

Dependiendo como se haya configurado el uploader de CarrierWave se debe modificar lo que se esta almacenando en la variable aws_path, es la ruta donde se encuentra el archivo en Amazon S3.

En aws_object se tiene la ruta completa del archivo y se especifica el bucket donde se encuentra el archivo.

Finalmente se envía el archivo con send_data.

Por último se debe agregar la acción al archivo routes:

get :download, :on => :collection