S3保存旧网址,更改回形针配置,将新网址设置为旧网址
Posted
技术标签:
【中文标题】S3保存旧网址,更改回形针配置,将新网址设置为旧网址【英文标题】:S3 save old url, change paperclip config, set new url as old 【发布时间】:2021-11-13 23:02:59 【问题描述】:所以事情是这样的:目前我们的文件,当用户下载它们时,名称类似于897123uiojdkashdu182uiej.pdf
。我需要将其更改为file-name.pdf.
从逻辑上讲,我去更改 paperclip.rb
配置:
Paperclip::Attachment.default_options.update(
path: '/:hash.:extension',
hash_secret: Rails.application.secrets.secret_key_base
)
到这里:
Paperclip::Attachment.default_options.update(
path: "/attachment/#SecureRandom.urlsafe_base64(64)/:filename",
hash_secret: Rails.application.secrets.secret_key_base
)
效果很好,文件名很棒。但是,由于路径的更改,旧文件现在无法访问。所以我想出了以下决定 首先我做了一个 rake 任务,它将旧路径存储在数据库中:
namespace :paperclip do
desc "Set old urls for attachments"
task :update_old_urls => :environment do
Asset.find_each do |asset|
if asset.attachment
attachment_url = asset.attachment.try!(:url)
file_url = "https:#attachment_url"
puts "Set old url asset attachment #asset.id - #file_url"
asset.update(old_url: file_url)
else
puts "No attachment found in asset #asset.id"
end
end
end
end
现在asset.old_url
存储文件的当前网址。然后我去更改配置,使文件无法访问。
现在是时候执行新的 rake 任务了:
require 'uri'
require 'open-uri'
namespace :paperclip do
desc "Recreate attachments and save them to new destination"
task :move_attachments => :environment do
Asset.find_each do |asset|
unless asset.old_url.blank?
url = asset.old_url
filename = File.basename(asset.attachment.path)
file = File.new("#Rails.root/tmp/#filename", "wb")
file.write(open(url).read)
if File.exists? file
puts "Re-saving asset attachment #asset.id - #filename"
asset.attachment = file
asset.save
# if there are multiple styles, you want to recreate them :
asset.attachment.reprocess!
file.close
else
puts "Missing file attachment #asset.id - #filename"
end
File.delete(file)
end
end
end
end
但我的计划根本没有奏效,我无法访问这些文件,而且asset.url
仍然不等于asset.old_url
。
非常感谢帮助!
【问题讨论】:
【参考方案1】:使用 S3,您可以将“保存时的文件名”设置为标题。具体来说,用户将获得一个 url https://foo.bar.com/mangled/path/some/weird/hash/whatever?options
,当浏览器提供保存时,您可以控制文件名(而不是 url)。
这个技巧依赖于浏览器从响应中读取Content-Disposition
标头,如果它读取Content-Disposition: attachment; filename="filename.jpg"
,它将保存(或要求用户另存为)filename.jpg
,独立于原始 URL。
您可以通过向 URL 添加一个参数或在文件上设置元数据来强制 S3 添加此标头。
前者可以通过将其传递给url
方法来完成:
has_attached_file :attachment,
s3_url_options: ->(instance)
response_content_disposition: "attachment; filename=\"#instance.filename\""
查看https://github.com/thoughtbot/paperclip/blob/v6.1.0/lib/paperclip/storage/s3.rb#L221-L225获取相关源代码。
后者可以通过回形针批量完成(您还应该将其配置为在新上传时执行此操作)。还要等很久!!
Asset.find_each do |asset|
next unless asset.attachment
s3_object = asset.attachment.s3_object
s3_object.copy_to(
s3_object,
metadata_directive: 'REPLACE',
content_disposition: "attachment; filename=\"#asset.filename\")"
)
end
# for new uploads
has_attached_file :attachment,
s3_headers: ->(att)
content_disposition: "attachment; filename=\"#att.model.filename\""
【讨论】:
以上是关于S3保存旧网址,更改回形针配置,将新网址设置为旧网址的主要内容,如果未能解决你的问题,请参考以下文章