Cómo extraer imágenes de un bucket que no poseo

Tengo un sitio con un montón de imágenes en un bucket de CDCK. Tengo un poco más de tiempo para sacarlas de ese bucket y moverlas al servidor local (y luego moverlas a otro bucket).

Las tareas uploads:analyze_missing_s3 y uploads:fix_missing_s3 no encuentran ningún problema, a pesar de que ~25K imágenes están en un bucket distante.

Sugerencia de función: Parece que EnsureS3UploadsExistence debería marcar las cargas como invalid_etag para las cargas que no están en el bucket correcto (es decir, ¿no tienen permisos para ese bucket?), pero no lo hace. Creo que tendría sentido que este o algún otro trabajo notara si las cargas estaban en un bucket sobre el cual el sitio actual no tiene control, o tal vez simplemente no es el bucket esperado para el sitio.

No puedo decir exactamente qué es verification_status, ya que no parece verificar que sea algo bueno.

Lo que intenté

ups=Upload.where("url like '//discourse-cloud-file-uploads.s3.dualstack.us-west-2.amazonaws.com/business6%'")                         
ups.update_all(verification_status: 3)

y luego

 rake uploads:fix_missing_s3 

Esa tarea de rake imprimió mensajes sobre la descarga de imágenes, pero un día después, cuando las publicaciones se volvieron a hornear, esas imágenes se ven como ![zawfI7C|346x500](upload://9L0PqY4QpqLOfexXHMMbv00EgaB.jpeg) en raw, pero enlazan a: https://test.literatecomputing.com/images/transparent.png

2 Me gusta

Tal vez un script ad hoc donde:\n\n1. Liste los archivos\n2. wget esta lista\n3. aws s3 sync los envíe a su bucket\n4. remap oldbucket newbucket

4 Me gusta

Bueno, vaya. Temía que esa fuera la respuesta.

Y supongo que @RGJ también lo hace así. :crying_cat_face:

1 me gusta

Pero no puedo enumerar los archivos porque están en tu bucket y estoy bastante seguro de que necesito credenciales para una lista.

rake uploads:fix_missing_s3 parece haber extraído (la mayoría?) de las cosas al sistema de archivos local (las cargas aún no están en s3 para este sitio).

Así que hice esto para arreglar las cargas:

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

Esto arregló la mayoría. Pero parece que hay algunas publicaciones que tienen una entrada uploads:// para la cual no hay una Upload en la base de datos. Volver a hornearlas termina con una transparent.png.

Así que luego intenté algo como esto:

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

Eso funciona en su mayor parte, pero en mis pruebas a veces no logro inferir la URL correcta de S3 del sha que infiero de la URL corta. No estoy seguro de cómo arreglar eso.

Además, a uno de ellos se le asignó de alguna manera un sha que era diferente del que estaba en el nombre del archivo de la ruta s3.

Mi pensamiento actual es comenzar yendo a través de todos los cooked y obteniendo todas las URL de https://discourse-cloud-file-uploads y luego actualizar los registros Upload que se refieren a ellos y crear los que faltan.

¿Me estoy perdiendo algo obvio?

¿No es la tabla de cargas una lista de archivos?

¡Eso pensé! Pero hay algunas uploads:// que existen en raw, que no tienen entradas en la tabla de subidas (al menos cuando busco el sha proporcionado por Upload.sha1_from_short_url(short_url)).

La mayoría, pero no todas, he podido inferir la URL del bucket del sha (no entiendo del todo 1X, 2X, 3X, pero parece que todas están en 3x).

Por lo tanto, no, no es el caso que la tabla de subidas sea una lista completa de los archivos en cuestión.