有没有办法在下载时更改/设置文件名?
示例:Jon Smith上传了他的头像,文件名为4321431-small.jpg
。在下载时,我想将文件重命名为jon_smith__headshot.jpg
。
查看:<%= url_for user.headshot_file %>
此url_for
从Amazon S3下载文件,但使用原始文件名。
我有什么选择?
@GuilPejon的方法将起作用。直接调用service_url
的问题是:
disk
,它将无法工作。它不适用于磁盘服务的原因是磁盘服务需要ActiveStorage::Current.host
来生成URL。并且ActiveStorage::Current.host
设置在app/controllers/active_storage/base_controller.rb
,因此当service_url
被调用时它将丢失。
ActiveStorage到目前为止提供了另一种访问附件URL的方法:
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
而已。
内置控制器为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
文件名。
我知道这已经回答了,但我想补充第二种做法。保存用户对象时,可以更新文件名。使用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