Table: RailsNotes
User: dreamable
Created at: 2021-04-29 22:17:39 UTC
Updated at: 2021-04-30 10:13:06 UTC
Reference:(Table ID 3, Record ID 44)

标题 :
Loop through all, zip and download from ActiveStorage
笔记 :

guide
rubyzip: zip dir recurisively

  def download
    if params[:id] # Folder ID
      folder = current_user.folders.find(params[:id])
      title = folder.name
      eids = [folder.id] | folder.descendants.map{|f| f.id}
      docs = current_user.documents.where(folder_id: eids);
    else
      title = current_user.name
      docs = current_user.documents;
    end
    title = title.downcase.gsub(/\s+/, '_');

    # Tmp folder to store the download files
    tmpd = "tmp/download/#{current_user.slug}"
    # Create a tmp folder if not exists
    FileUtils.rm_rf([tmpd,"#{tmpd}.zip"]);
    FileUtils.mkdir_p(tmpd);
    # Download and save documents to our tmp folder
    docs.each do |doc|
      file = doc.file; folder = doc.folder;
      dir = folder ? "#{tmpd}/#{folder.full_path}" : tmpd
      FileUtils.mkdir_p(dir) unless Dir.exists?(dir)
      fname = file.filename.to_s
      if File.exist?("#{dir}/#{fname}")  # incase two file with same name
        fname = "DUP_ID#{doc.id}_#{fname}"
      end
      # User should be able to download files if not yet removed from tmp folder
      # if the folder is already there, we'd get an error
      download_doc_to_dir(file, dir, fname)
    end
    #---------- Convert to .zip --------------------------------------- #
    zg = ZipFileGenerator.new(tmpd,"#{tmpd}.zip")
    zg.write
    # Sends the *.zip file to be download to the client's browser
    send_file(Rails.root.join("#{tmpd}.zip"), :type => 'application/zip', :filename => "#{title}.zip", :disposition => 'attachment')
    # TODO: Remove dir but leave zip file
    FileUtils.rm_rf(tmpd)
  end

  def download_doc_to_dir(doc, tmpd, fname)
    File.open(File.join(tmpd, fname), 'wb') do |file|
      doc.download { |chunk| file.write(chunk) }
    end
  end
Tag: