Come estrarre immagini da un bucket che non possiedo

Ho un sito con un sacco di immagini su un bucket CDCK. Ho poco tempo per estrarle da quel bucket e spostarle sul server locale (e poi spostarle su un altro bucket).

I task rake uploads:analyze_missing_s3 e uploads:fix_missing_s3 non trovano problemi, anche se circa 25.000 immagini si trovano su un bucket distante.

Suggerimento Funzionalità: Sembra che EnsureS3UploadsExistence dovrebbe contrassegnare gli upload come invalid_etag per gli upload che non si trovano nel bucket giusto (cioè, non hanno i permessi per quel bucket?), ma non lo fa. Penso che avrebbe senso che questo o qualche altro job noti se gli upload si trovassero in un bucket su cui il sito attuale non ha controllo, o forse semplicemente non è il bucket previsto per il sito.

Non riesco a capire bene cosa sia verification_status, dato che non sembra verificare che sia qualcosa di buono.

Cosa ho provato

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

e poi

 rake uploads:fix_missing_s3 

Quel task rake ha stampato messaggi sul download di immagini, ma un giorno dopo, quando i post sono stati rebaked, quelle immagini appaiono come ![zawfI7C|346x500](upload://9L0PqY4QpqLOfexXHMMbv00EgaB.jpeg) in raw, ma linkano a: https://test.literatecomputing.com/images/transparent.png

2 Mi Piace

Forse uno script ad hoc in cui:\n\n1. Elenca i file\n2. wget questo elenco\n3. aws s3 sync li trasferisce nel tuo bucket\n4. remap oldbucket newbucket

4 Mi Piace

Beh, che seccatura. Temevo che quella potesse essere la risposta.

E immagino che sia così che fa anche @RGJ. :crying_cat_face:

1 Mi Piace

Ma non riesco a elencare i file perché sono sul tuo bucket e sono abbastanza sicuro che avrò bisogno delle credenziali per un elenco.

rake uploads:fix_missing_s3 sembra aver scaricato (la maggior parte?) delle cose nel file system locale (gli upload non sono ancora su s3 per questo sito)

Quindi ho fatto questo per sistemare gli upload:

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
        # recupera i mancanti
        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

Questo ha sistemato la maggior parte di essi. Ma sembrano esserci alcuni post che hanno una voce uploads:// per la quale non c’è un Upload nel database. Ripastarli finisce per creare un transparent.png.

Quindi ho provato qualcosa del genere:

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
    # prova a trovarlo 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
    # crea upload per 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 "Ce l'abbiamo fatta! #{upload.id}"
    else
      puts "Dannazione. #{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

Questo funziona per la maggior parte, ma nei miei test a volte non riesco a dedurre l’URL S3 corretto dallo sha che deduco dall’URL breve. Non sono sicuro di come risolvere questo problema.

Inoltre, uno di essi ha finito per avere uno sha diverso da quello nel nome del file del percorso s3.

Il mio attuale pensiero ora è iniziare andando attraverso tutti i cooked e ottenendo tutti gli URL https://discourse-cloud-file-uploads e poi procedere all’aggiornamento dei record Upload che vi fanno riferimento e alla creazione di quelli mancanti.

Mi sto perdendo qualcosa di ovvio?

La tabella degli upload non è un elenco di file?

Questo è quello che pensavo! Ma ci sono alcuni uploads:// che esistono in raw, che non hanno voci nella tabella degli upload (almeno quando cerco lo sha fornito da Upload.sha1_from_short_url(short_url)).

La maggior parte, ma non tutti, sono riuscito a dedurre l’URL del bucket dallo sha (non capisco bene 1X, 2X, 3X, ma sembra che siano tutti in 3x).

Quindi, no, non è vero che la tabella degli upload sia un elenco completo dei file in questione.