【问题标题】:Force a link to download an MP3 rather than play it?强制链接下载 MP3 而不是播放?
【发布时间】:2016-12-06 08:35:46
【问题描述】:

我有一个锚链接

<a href="http://bucket_name.amazonaws.com/uploads/users/4/songs/7/test.mp3">Download</a> 

如何做到这一点,当用户点击它时,它实际上会打开一个弹出窗口,要求用户保存文件而不是尝试在浏览器上播放文件?

编辑:

我正在阅读这个article

  def download
    data = open(Song.first.attachment)
    send_data data.read, :type => data.content_type, :x_sendfile=>true
  end

文章建议使用 x_sendfile,因为 send_file 占用一个 http 进程,在下载完成之前可能会挂起应用程序。

其次,我使用的是 send_data 而不是 send_file,如果文件是远程的(即托管在 Amazon S3 上),这似乎可以工作。正如article所建议的那样。

我提到的那篇文章发表于 2009 年。x_sendfile=>true 还需要吗?如果不包含它会挂起应用程序吗?

我真的应该使用 send_data 还是 send_file?

【问题讨论】:

  • 很好的解决方案,谢谢。我必须做的唯一改变是你使用 data = open(Song.first.attachment_url),否则我会得到一个错误:'can't convert Paperclip::Attachment into String'。

标签: ruby-on-rails


【解决方案1】:

如果您不想使用 HTTP 服务器配置,可以使用单独的控制器管理文件下载。

因此您可以将send_filedisposition 选项作为attachment

【讨论】:

  • 这会占用一个单一的http线程吗?即在文件下载完成之前应用会挂起吗?
  • 我得到:无法读取文件actual_bucket_name.s3.amazonaws.com/uploads/users/4/songs/7/…。我的方法如下: def download send_file Song.first.attachment, :type=>"application/mp3", :x_sendfile=>true, :disposition => 'inline' end
【解决方案2】:

取决于您/您在哪里提供文件本身。我没有使用 ruby​​ 的经验,但如果您可以更改 http 响应的标头(大多数平台提供此选项),您可以强制下载。这需要:

Content-Type: application/force-download

我猜它会默认使用“Content-type: application/octet-stream”,这会导致浏览器播放它。

但这只有在您可以控制保存实际文件的服务器/位置时才有效,因为您需要在文件发送到浏览器时更改响应。

【讨论】:

    【解决方案3】:

    跳过控制器操作

    你甚至不需要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=\"#{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 的指导。

    【讨论】:

    • 上面的“模型方法”不能按原样工作。 aws-sdk 中的url_for 方法用于S3Object,而上面声明的s3 变量只是获取存储桶。您需要将 .objects[ 'key' ] 添加到该行的末尾才能使其正常工作。
    • @DanWeaver 你说得对。我已经更新它以引用对象,而不仅仅是现在的存储桶。看看吧。
    • 我在尝试这个时遇到动态常量赋值错误。
    • @ddonche 尝试将S3 = AWS::S3.new.buckets[ 'bucket_name' ] 移动到attachment.rb 文件的顶部,这样就不会在每次调用#download 或使用小写s3 时重新定义它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-07
    • 2021-08-19
    • 2014-05-22
    • 1970-01-01
    • 2021-07-07
    • 2010-11-03
    • 2013-02-24
    相关资源
    最近更新 更多