español aws ruby-on-rails ruby ruby-on-rails-3 amazon-s3 ruby-on-rails-3.2

ruby on rails - aws - ¿Usando send_file para descargar un archivo de Amazon S3?



aws en español (5)

Mantenga las cosas simples para el usuario

Creo que la mejor manera de manejar esto es usando una url S3 que expira. Los otros métodos tienen los siguientes problemas:

  • El archivo se descarga al servidor primero y luego al usuario.
  • El uso de send_data no produce la "descarga del navegador" esperada.
  • Vincula el proceso de Ruby.
  • Requiere una acción de controlador de download adicional.

Mi implementación se ve así:

En su attachment.rb

def download_url S3 = AWS::S3.new.buckets[ ''bucket_name'' ] # This can be done elsewhere as well, # e.g config/environments/development.rb url_options = { expires_in: 60.minutes, use_ssl: true, response_content_disposition: "attachment; filename=/"#{attachment_file_name}/"" } S3.objects[ self.path ].url_for( :read, url_options ).to_s end

En tus puntos de vista

<%= link_to ''Download Avicii by Avicii'', attachment.download_url %>

Eso es.

Si aún desea mantener su acción de download por alguna razón, simplemente use esto:

En tus attachments_controller.rb

def download redirect_to @attachment.download_url end

Gracias a guilleva por su guía.

Tengo un enlace de descarga en mi aplicación desde el cual los usuarios deberían poder descargar los archivos que están almacenados en s3. Estos archivos serán accesibles públicamente en las URL que se parecen a

https://s3.amazonaws.com/:bucket_name/:path/:to/:file.png

El enlace de descarga golpea una acción en mi controlador:

class AttachmentsController < ApplicationController def show @attachment = Attachment.find(params[:id]) send_file(@attachment.file.url, disposition: ''attachment'') end end

Pero recibo el siguiente error cuando intento descargar un archivo:

ActionController::MissingFile in AttachmentsController#show Cannot read file https://s3.amazonaws.com/:bucket_name/:path/:to/:file.png Rails.root: /Users/user/dev/rails/print Application Trace | Framework Trace | Full Trace app/controllers/attachments_controller.rb:9:in `show''

El archivo definitivamente existe y es accesible públicamente en la url en el mensaje de error.

¿Cómo permito que los usuarios descarguen archivos S3?


Acabo de migrar mi carpeta public/system a Amazon S3. Las soluciones anteriores ayudan, pero mi aplicación acepta diferentes tipos de documentos. Entonces, si necesitas el mismo comportamiento, esto me ayuda:

@document = DriveDocument.where(id: params[:id]) if @document.present? @document.track_downloads(current_user) if current_user data = open(@document.attachment.expiring_url) send_data data.read, filename: @document.attachment_file_name, type: @document.attachment_content_type, disposition: ''attachment'' end

El archivo se está DriveDocument en el campo de attachment del objeto DriveDocument . Espero que esto ayude.


Lo siguiente fue lo que terminó funcionando bien para mí. Obtener los datos brutos del objeto S3 y luego usar send_data para pasarlos al navegador.

Usando la documentación de gemas aws-sdk encontrada aquí http://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/S3Object.html

método de controlador completo

def download AWS.config({ access_key_id: "SECRET_KEY", secret_access_key: "SECRET_ACCESS_KEY" }) send_data( AWS::S3.new.buckets["S3_BUCKET"].objects["FILENAME"].read, { filename: "NAME_YOUR_FILE.pdf", type: "application/pdf", disposition: ''attachment'', stream: ''true'', buffer_size: ''4096'' } ) end


Para enviar un archivo desde su servidor web,

  • necesitas descargarlo de S3 (ver la respuesta de @nzajt ) o

  • puedes redirect_to @attachment.file.expiring_url(10)


También puedes usar send_data .

Me gusta esta opción porque tienes un mejor control. No está enviando usuarios a s3, lo que puede ser confuso para algunos usuarios.

Solo agregaría un método de descarga al AttachmentsController

def download data = open("https://s3.amazonaws.com/PATTH TO YOUR FILE") send_data data.read, filename: "NAME YOU WANT.pdf", type: "application/pdf", disposition: ''inline'', stream: ''true'', buffer_size: ''4096'' end

y agrega la ruta

get "attachments/download"