Но я не могу получить список файлов, так как они находятся в вашем бакете, и я почти уверен, что для этого нужны учетные данные.
rake uploads:fix_missing_s3, похоже, загрузил (большинство?) файлы в локальную файловую систему (загрузки для этого сайта еще не находятся в S3).
Поэтому я сделал следующее, чтобы исправить загрузки:
def fix_bad_uploads(bad_uploads)
fixed = 0
retrieved = 0
missing = 0
bad_bucket="//discourse-cloud-file-uploads.s3.dualstack.us-west-2.amazonaws.com/business6/uploads/forumosa"
bad_uploads.each do |upload|
url = URI.parse("https:"+upload.url)
upload.url=upload.url.gsub(bad_bucket,"/uploads/default")
if File.exists?("/shared/#{upload.url}")
fixed += 1
print "1"
upload.save
# posts = Post.where("raw like '%#{upload.short_url}%'")
# posts.each do |post|
# post.rebake!
# print "."
# end
else
begin
# retrieve missing
filename = "/shared#{upload.url}"
dirname = File.dirname(filename)
unless File.directory?(dirname)
FileUtils.mkdir_p(dirname)
end
file = File.new(filename, "w")
Net::HTTP.start(url.host) do |http|
resp = http.get(url.path)
open(file, "wb") do |file|
file.write(resp.body)
end
end
file.close
print "+"
upload.save if File.exists?(filename)
rescue => e
puts "bad: #{e}"
missing += 0
sleep 1
print "0"
end
end
end
end
Это исправило большинство из них. Но, похоже, есть некоторые посты, которые содержат запись uploads://, для которой в базе данных нет записи Upload. Пересборка таких постов приводит к появлению transparent.png.
Поэтому я попробовал что-то вроде этого:
def get_missing_short_url(short_url)
prefix = "https://discourse-cloud-file-uploads.s3.dualstack.us-west-2.amazonaws.com/business6/uploads/forumosa/original/3X"
remove_url = "https://discourse-cloud-file-uploads.s3.dualstack.us-west-2.amazonaws.com/business6/uploads/forumosa/"
sha1= Upload.sha1_from_short_url(short_url)
extension = short_url.split(".").last
upload = Upload.find_by(sha1: sha1)
if !upload
# try to find it in s3
one = sha1[0]
two=sha1[1]
url_link = "#{prefix}/#{one}/#{two}/#{sha1}.#{extension}"
puts "URL: #{url_link}"
sleep 1
url = URI.parse(url_link)
full_filename = url_link.gsub(remove_url,"/shared/uploads/default/")
filename = "/tmp/#{File.basename(url_link.gsub(remove_url,"/shared/uploads/default/"))}"
dirname = File.dirname(filename)
unless File.directory?(dirname)
FileUtils.mkdir_p(dirname)
end
File.open(filename, "w") do |file|
Net::HTTP.start(url.host) do |http|
resp = http.get(url.path)
open(file, "wb") do |file|
file.write(resp.body)
end
end
end
# make upload for file
File.open(filename, "r") do |file|
upload = UploadCreator.new(
file,
File.basename(file),
).create_for(Discourse.system_user.id)
end
if upload.persisted?
puts "We did it! #{upload.id}"
else
puts "darn. #{upload.errors.full_messages}"
sleep 5
end
File.open(filename, "w") do |file|
Net::HTTP.start(url.host) do |http|
resp = http.get(url.path)
open(file, "wb") do |file|
file.write(resp.body)
end
end
end
end
upload
end
Это в основном работает, но в моих тестах иногда мне не удается корректно определить правильный URL S3 из sha, который я получаю из short_url. Не уверен, как это исправить.
Кроме того, один из файлов каким-то образом оказался с sha, отличным от того, что указан в имени файла пути S3.
Моя текущая идея заключается в том, чтобы начать с перебора всех записей cooked, извлечь все URL-адреса https://discourse-cloud-file-uploads, а затем обновить записи Upload, которые на них ссылаются, и создать отсутствующие.
Не упускаю ли я что-то очевидное?