Wie man Bilder aus einem Bucket zieht, der mir nicht gehört

Ich habe eine Website mit einer Reihe von Bildern in einem CDCK-Bucket. Ich habe nur noch etwas länger Zeit, um sie aus diesem Bucket zu holen und auf den lokalen Server zu verschieben (und dann in einen anderen Bucket zu verschieben).

Die Rake-Tasks uploads:analyze_missing_s3 und uploads:fix_missing_s3 finden keine Probleme, obwohl ~25.000 Bilder in einem entfernten Bucket sind.

Funktionsvorschlag: Es scheint, als ob EnsureS3UploadsExistence Uploads als invalid_etag für Uploads markieren sollte, die sich nicht im richtigen Bucket befinden (d. h. keine Berechtigungen für diesen Bucket haben?), aber das tut es nicht. Ich denke, es wäre sinnvoll, wenn diese oder eine andere Aufgabe feststellen würde, ob sich Uploads in einem Bucket befinden, über den die aktuelle Website keine Kontrolle hat, oder vielleicht einfach nicht der erwartete Bucket für die Website ist.

Ich kann nicht genau sagen, was verification_status ist, da es nicht zu überprüfen scheint, ob es etwas Gutes ist.

Was ich versucht habe

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

und dann

 rake uploads:fix_missing_s3 

Diese Rake-Aufgabe gab Meldungen über das Herunterladen von Bildern aus, aber einen Tag später, als die Beiträge neu gebacken wurden, sahen diese Bilder in raw wie ![zawfI7C|346x500](upload://9L0PqY4QpqLOfexXHMMbv00EgaB.jpeg) aus, aber sie verlinkten zu: https://test.literatecomputing.com/images/transparent.png

2 „Gefällt mir“

Vielleicht ein Adhoc-Skript, bei dem Sie:

  1. Dateien auflisten
  2. Diese Liste mit wget herunterladen
  3. Sie mit aws s3 sync in Ihren Bucket synchronisieren
  4. remap oldbucket newbucket
4 „Gefällt mir“

Nun, Ärger. Ich befürchtete, das könnte die Antwort sein.

Und ich schätze, so macht es @RGJ auch. :crying_cat_face:

1 „Gefällt mir“

Aber ich kann keine Dateien auflisten, da sie sich in Ihrem Bucket befinden und ich ziemlich sicher bin, dass ich Anmeldeinformationen für eine Liste benötige.

rake uploads:fix_missing_s3 scheint (die meisten?) Dinge auf das lokale Dateisystem gezogen zu haben (Uploads sind für diese Website noch nicht auf S3).

Also habe ich Folgendes getan, um die Uploads zu reparieren:

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

Dies hat die meisten behoben. Aber es scheint einige Beiträge zu geben, die einen uploads://-Eintrag haben, für den es keinen Upload in der Datenbank gibt. Das erneute Backen dieser führt zu einem transparent.png.

Dann habe ich versucht, so etwas zu tun:

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

Das funktioniert größtenteils, aber in meinen Tests gelingt es mir manchmal nicht, die richtige S3-URL aus dem SHA abzuleiten, den ich aus der Kurz-URL ableite. Ich bin mir nicht sicher, wie ich das beheben soll.

Außerdem hat einer von ihnen irgendwie einen sha bekommen, der sich von dem im Dateinamen des S3-Pfads unterschied.

Mein aktueller Gedanke ist, zunächst alle cooked durchzugehen und alle https://discourse-cloud-file-uploads-URLs zu extrahieren und dann die Upload-Datensätze, die sich darauf beziehen, zu aktualisieren und die fehlenden zu erstellen.

Fehlt mir etwas Offensichtliches?

Ist die Uploads-Tabelle keine Liste von Dateien?

Das dachte ich auch! Aber es gibt einige uploads://, die in raw existieren und keine Einträge in der Uploads-Tabelle haben (zumindest nicht, wenn ich nach der SHA-Nummer suche, die von Upload.sha1_from_short_url(short_url) bereitgestellt wird).

Die meisten, aber nicht alle, konnte ich von der SHA-Nummer auf die Bucket-URL schließen (ich verstehe 1X, 2X, 3X nicht ganz, aber es scheint, dass sie alle in 3x sind).

Also, nein, es ist nicht so, dass die Uploads-Tabelle eine vollständige Liste der betreffenden Dateien ist.