RubyZip: невозможно найти путь к файлу, хранящемуся в Active Storage

Я использую Rails 5.2 и ActiveStorage, чтобы пользователи могли загружать файлы в мое приложение. У меня есть все загруженные файлы, отображаемые в таблице, и я могу выбрать, какие из них я хочу загрузить. После выбора я смогу загрузить их все в виде zip-файла. Чтобы заархивировать файлы, я использую Rubyzip и не могу нормально работать.

Я пробовал два способа:
1 - Я пробовал таким образом и столкнулся с этой ошибкой
Нет такого файла или каталога @ rb_sysopen - /rails/active_storage/blobs/..../2234.py
Это мой контроллер:

def batch_download
  if params["record"].present?
    ids = params["record"].to_unsafe_h.map(&:first)

    if ids.present?
      folder_path = "#{Rails.root}/public/downloads/"
      zipfile_name = "#{Rails.root}/public/archive.zip"

      FileUtils.remove_dir(folder_path) if Dir.exist?(folder_path)
      FileUtils.remove_entry(zipfile_name) if File.exist?(zipfile_name)
      Dir.mkdir("#{Rails.root}/public/downloads")

      Record.where(id: ids).each do |attachment|
        open(folder_path + "#{attachment.file.filename}", 'wb') do |file|
          file << open("#{rails_blob_path(attachment.file)}").read
        end
      end

      input_filenames = Dir.entries(folder_path).select {|f| !File.directory? f}

      Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
        input_filenames.each do |attachment|
          zipfile.add(attachment,File.join(folder_path,attachment))
        end
      end

      send_file(File.join("#{Rails.root}/public/", 'archive.zip'), :type => 'application/zip', :filename => "#{Time.now.to_date}.zip")
    end
  else
    redirect_back fallback_location: root_path
  end
end

2 - Во-вторых, я попытался выполнить документацию по rubyzip, и ошибка была немного другой.
Нет такого файла или каталога @ rb_file_s_lstat - /rails/active_storage/blobs/..../2234.py

if ids.present?
      folder = []
      input_filenames = []
      Record.where(id: ids).each do |attachment| 
        input_filenames.push("#{attachment.file.filename}")
        pre_path = "/rails/active_storage/blobs/"
        path_find = "#{rails_blob_path(attachment.file)}"
        folder.push(pre_path + path_find.split('/')[4])
      end
      container = Hash[folder.zip(input_filenames)]

      zipfile_name = "/Users/fahimabdullah/Documents/archive.zip"

      Zip::File.open(zipfile_name, Zip::File::CREATE) do |zipfile|
        # input_filenames.each do |filename|
        container.map do |path, filename|
        zipfile.add(filename, File.join(path, filename))
        end
        zipfile.get_output_stream("myFile") { |f| f.write "myFile contains just this" }
      end

Я ожидаю, что он загрузит zip-файл, содержащий все файлы внутри. И это мой первый вопрос, извините, пожалуйста, если вопрос был слишком длинным. Спасибо.


person Fahim Abdullah    schedule 16.01.2019    source источник


Ответы (1)


У меня была аналогичная проблема, но я увидел, что на нее еще нет ответа. Несмотря на то, что он немного старше и вы, вероятно, уже решили это, вот мой подход. Хитрость заключалась в том, чтобы создать временный файл между

def whatever
    zip_file = Tempfile.new('invoices.zip')

    Zip::File.open(zip_file.path, Zip::File::CREATE) do |zipfile|
      invoices.each do |invoice|
        next unless invoice.attachment.attached?

        overlay = Tempfile.new(['overlay', '.pdf'])
        overlay.binmode
        overlay.write(invoice.attachment.download)
        overlay.close
        overlay.path

        zipfile.add(invoice.filename, File.join(overlay.path))
      end
    end

    invoices_zip = File.read(zip_file.path)

    UserMailer.with(user: user).invoice_export(invoices_zip, 'invoices.zip').deliver_now
  ensure
    zip_file.close
    zip_file.unlink
  end
person Devchris    schedule 19.07.2020