S3 保存旧 url,更改回形针配置,将新 url 设置为旧
S3 save old url, change paperclip config, set new url as old
事情是这样的:目前我们的文件,当用户下载它们时,名称类似于 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
存储文件的当前 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
。
非常感谢帮助!
使用 S3,您可以将“保存时的文件名”设置为 header。具体来说,用户将进入 url https://foo.bar.com/mangled/path/some/weird/hash/whatever?options
并且当浏览器提供保存时,您可以控制文件名(而不是 url)。
这个技巧依赖于浏览器从响应中读取 Content-Disposition
header,如果它读取 Content-Disposition: attachment; filename="filename.jpg"
它将保存(或要求用户另存为)filename.jpg
,独立于原来的URL.
您可以通过向 URL 添加一个参数或在文件上设置元数据来强制 S3 添加此 header。
前者可以通过将其传递给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}\""}
}
事情是这样的:目前我们的文件,当用户下载它们时,名称类似于 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
存储文件的当前 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
。
非常感谢帮助!
使用 S3,您可以将“保存时的文件名”设置为 header。具体来说,用户将进入 url https://foo.bar.com/mangled/path/some/weird/hash/whatever?options
并且当浏览器提供保存时,您可以控制文件名(而不是 url)。
这个技巧依赖于浏览器从响应中读取 Content-Disposition
header,如果它读取 Content-Disposition: attachment; filename="filename.jpg"
它将保存(或要求用户另存为)filename.jpg
,独立于原来的URL.
您可以通过向 URL 添加一个参数或在文件上设置元数据来强制 S3 添加此 header。
前者可以通过将其传递给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}\""}
}