كيفية سحب الصور من دلو لا أملكه

لدي موقع به مجموعة من الصور في دلو CDCK. لدي وقت قصير لسحبها من هذا الدلو ونقلها إلى الخادم المحلي (ثم نقلها إلى دلو آخر).

لا تجد المهام uploads:analyze_missing_s3 و uploads:fix_missing_s3 أي مشاكل، على الرغم من أن حوالي 25 ألف صورة موجودة في دلو بعيد.

اقتراح ميزة: يبدو أن EnsureS3UploadsExistence يجب أن يضع علامة invalid_etag على التحميلات التي ليست في الدلو الصحيح (أي، لا تملك أذونات لهذا الدلو؟)، ولكنه لا يفعل ذلك. أعتقد أنه سيكون من المنطقي أن تلاحظ هذه المهمة أو مهمة أخرى ما إذا كانت التحميلات موجودة في دلو لا يتحكم فيه الموقع الحالي، أو ربما ليس الدلو المتوقع للموقع.

لا يمكنني تحديد ما هو verification_status بالضبط، حيث لا يبدو أنه يتحقق من أنه شيء جيد.

ما جربته

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

ثم

 rake uploads:fix_missing_s3 

طبعت تلك المهمة رسائل حول تنزيل الصور، ولكن بعد يوم عندما تم إعادة خبز المشاركات، بدت تلك الصور مثل ![zawfI7C|346x500](upload://9L0PqY4QpqLOfexXHMMbv00EgaB.jpeg) في raw، ولكنها ترتبط بـ: https://test.literatecomputing.com/images/transparent.png

إعجابَين (2)

ربما نص برمجي مخصص حيث تقوم بما يلي:

  1. سرد الملفات
  2. wget لهذه القائمة
  3. aws s3 sync عليها إلى الدلو الخاص بك
  4. remap oldbucket newbucket
4 إعجابات

حسنًا، يا إلهي. كنت أخشى أن يكون هذا هو الجواب.

وأعتقد أن هذا هو الأسلوب الذي يتبعه @RGJ أيضًا. :crying_cat_face:

إعجاب واحد (1)

لكن لا يمكنني سرد الملفات لأنها موجودة على الحاوية الخاصة بك وأنا متأكد من أنني بحاجة إلى بيانات اعتماد للقائمة.

يبدو أن 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 الذي أستنتجه من عنوان URL القصير. لست متأكدًا من كيفية إصلاح ذلك.

أيضًا، انتهى الأمر بأحدها بطريقة ما بـ sha مختلف عن الـ sha الموجود في اسم ملف مسار S3.

تفكيري الحالي الآن هو البدء بالمرور عبر كل cooked والحصول على جميع عناوين URL لـ https://discourse-cloud-file-uploads ثم المتابعة لتحديث سجلات Upload التي تشير إليها وإنشاء السجلات المفقودة.

هل فاتني شيء واضح؟

أليست جداول التحميلات قائمة بالملفات؟

هذا ما اعتقدته! ولكن هناك بعض uploads:// موجودة في raw، لا تحتوي على إدخالات في таблиعة uploads (على الأقل عندما أبحث عن sha كما هو مقدم من Upload.sha1_from_short_url(short_url)).

معظمها، ولكن ليس كلها، تمكنت من استنتاج عنوان URL للمخزن المؤقت من sha (لا أفهم تمامًا 1X، 2X، 3X، ولكن يبدو أنها كلها في 3x).

لذلك، لا، ليس صحيحًا أن جدول uploads هو قائمة كاملة بالملفات المعنية.