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

问题描述 投票:2回答:4

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

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

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

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

我有什么选择?

ruby-on-rails amazon-s3 filenames rails-activestorage
4个回答
1
投票

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

  1. 它是短暂的(不是铁路团队推荐)
  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 repo中看到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而已。


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
投票

我知道这已经回答了,但我想补充第二种做法。保存用户对象时,可以更新文件名。使用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

0
投票

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

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

rails_blob_url(user.headshot_file, filename: "jon_smith__headshot.jpg"`enter code here`)
© www.soinside.com 2019 - 2024. All rights reserved.