S3上的Rails + ActiveStorage:下载时设置文件名?

时间:2018-02-07 20:30:37

标签: ruby-on-rails amazon-s3 filenames rails-activestorage

有没有办法在下载时更改/设置文件名?

示例:Jon Smith上传了他的头像,文件名为4321431-small.jpg。在下载时,我想将文件重命名为jon_smith__headshot.jpg

查看: <%= url_for user.headshot_file %>

url_for从Amazon S3下载文件,但使用原始文件名。

我有什么选择?

4 个答案:

答案 0 :(得分:4)

内置控制器为blob提供存储的文件名。您可以实现一个自定义控制器,使用不同的文件名为它们提供服务:

class HeadshotsController < ApplicationController
  before_action :set_user

  def show
    redirect_to @user.headshot.service_url(filename: filename)
  end

  private
    def set_user
      @user = User.find(params[:user_id])
    end

    def filename
      ActiveStorage::Filename.new("#{user.name.parameterize(separator: "_")}__headshot#{user.headshot.filename.extension_with_delimiter}")
    end
end

从5.2.0 RC2开始,您不需要传递ActiveStorage::Filename;您可以改为传递String文件名。

答案 1 :(得分:1)

我知道已经回答了这个问题,但是我想添加第二种方法。保存用户对象时,您可以更新文件名。使用OP的user模型示例和headshot_file字段,这是解决此问题的方法:

# app/models/user.rb

after_save :set_filename

def set_filename
  file.blob.update(filename: "ANYTHING_YOU_WANT.#{file.filename.extension}") if file.attached?
end

答案 2 :(得分:1)

@GuilPejon的方法将起作用。直接调用service_url的问题是:

  1. 寿命短(不被Rails团队推荐)
  2. 如果该服务在开发模式下为disk,则它将无法正常工作。

对于磁盘服务不起作用的原因是,磁盘服务要求存在ActiveStorage::Current.host才能生成URL。并且ActiveStorage::Current.host已在app/controllers/active_storage/base_controller.rb中设置,因此在调用service_url时它将丢失。

截至目前,ActiveStorage提供了访问附件URL的另一种方法:

  1. 使用rails_blob_(url|path)(推荐方式)

但是,如果使用此选项,则只能提供content-disposition,而不能提供文件名。

如果您在ActiveStorage存储库中看到config/routes.rb,则会找到以下代码。

    get "/rails/active_storage/blobs/:signed_id/*filename" => "active_storage/blobs#show", as: :rails_service_blob

    direct :rails_blob do |blob, options|
        route_for(:rails_service_blob, blob.signed_id, blob.filename, options)
    end

,当您查看blobs_controller时,会发现以下代码:

    def show
        expires_in ActiveStorage::Blob.service.url_expires_in
        redirect_to @blob.service_url(disposition: params[:disposition])
    end

因此很明显,在rails_blob_(url|path)中,您只能通过disposition,仅此而已。

答案 3 :(得分:0)

我还没有玩过ActiveStorage,所以这是一个黑暗中的镜头。

查看S3服务的ActiveStorage source,看起来您可以指定上传的文件名和处置方式。从guides开始,您似乎可以使用rails_blob_path访问上传的原始网址并传递这些参数。因此你可以尝试:

rails_blob_url(user.headshot_file, filename: "jon_smith__headshot.jpg"`enter code here`)