64

アプリにダウンロードリンクがあり、そこからユーザーはs3に保存されているファイルをダウンロードできます。これらのファイルは、次のようなURLで公開されます。

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

ダウンロードリンクが私のコントローラーのアクションにヒットします:

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

しかし、ファイルをダウンロードしようとすると、次のエラーが発生します。

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'

このファイルは間違いなく存在し、エラーメッセージのURLから一般公開されています。

ユーザーがS3ファイルをダウンロードできるようにするにはどうすればよいですか?

4

7 に答える 7

92

を使用することもできますsend_data

あなたがより良いコントロールを持っているので、私はこのオプションが好きです。一部のユーザーを混乱させる可能性があるs3にユーザーを送信していません。

ダウンロード方法を追加するだけです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 

ルートを追加します

get "attachments/download"
于 2013-02-22T15:59:03.567 に答える
37

ユーザーにとって物事をシンプルに保つ

これを処理する最良の方法は、期限切れのS3URLを使用することだと思います。他の方法には次の問題があります。

  • ファイルは最初にサーバーにダウンロードされ、次にユーザーにダウンロードされます。
  • を使用send_dataしても、期待される「ブラウザのダウンロード」は生成されません。
  • Rubyプロセスを結び付けます。
  • 追加のdownloadコントローラーアクションが必要です。

私の実装は次のようになります。

あなたの中で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

あなたの見解では

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

それでおしまい。


downloadそれでも何らかの理由でアクションを継続したい場合は、次を使用してください。

あなたの中でattachments_controller.rb

def download
  redirect_to @attachment.download_url
end

彼の指導をしてくれたguillevaに感謝します。

于 2014-04-18T19:58:38.233 に答える
32

Webサーバーからファイルを送信するには、

  • S3からダウンロードする必要があります(@nzajtの回答を参照)または

  • あなたはできるredirect_to @attachment.file.expiring_url(10)

于 2012-09-05T09:09:39.810 に答える
6

public/systemフォルダをAmazonS3に移行しました。上記の解決策は役に立ちますが、私のアプリはさまざまな種類のドキュメントを受け入れます。したがって、同じ動作が必要な場合、これは私に役立ちます。

@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

attachmentファイルはオブジェクトのフィールドに保存されていDriveDocumentます。これがお役に立てば幸いです。

于 2015-01-12T03:44:12.680 に答える
5

以下は私にとってうまくいったものです。S3オブジェクトから生データを取得し、それを使用send_dataしてブラウザに渡します。

aws-sdkここにあるgemドキュメントを使用するhttp://docs.aws.amazon.com/AWSRubySDK/latest/AWS/S3/S3Object.html

フルコントローラー方式

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
于 2014-03-04T20:10:57.553 に答える
0

ユーザーがS3ファイルをダウンロードできるようにするにはどうすればよいですか?

ユーザーが後でダウンロードしたいときにパッチを適用するのではなく、S3にアップロードする前にファイルにメタデータを設定できる場合、このソリューションははるかに簡単です。

https://stackoverflow.com/a/24297799/763231

を使用している場合はfog、次のようなことができます。

has_attached_file :report,
  fog_file: lambda { |attachment|
    {
      content_type: 'text/csv',
      content_disposition: "attachment; filename=#{attachment.original_filename}",
    }
  }

ストレージプロバイダーとしてAmazonS3を使用している場合は、次のように機能するはずです。

has_attached_file :report
  s3_headers: lambda { |attachment|
    { 
      'Content-Type' => 'text/csv',
      'Content-Disposition' => "attachment; filename=#{attachment.original_filename}",
    }
  }
于 2020-07-30T04:18:13.303 に答える
-1

def download_pdf @ post = @ post.avatar.service_url

send_data(

    "#{Rails.root}/public/#{@post}",
    filename: "#{@post}",
    type: "image/*",
    disposition: 'inline', stream: 'true', buffer_size: '4096'
)

終わり

于 2020-06-12T11:36:11.710 に答える