diff --git a/Gemfile b/Gemfile
index a7c99af1c226ea9c1d2b84a0b83478f7f998ef71..126ab31b806ec50ee14e13efa29bdec37715ed4f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -60,7 +60,7 @@ gem 'bootstrap-sass'
 gem 'select2-rails'
 
 #Gruff (graphs and charts)
-#gem 'rmagick'
+gem 'rmagick'
 #gem 'gruff'
 
 #RSolr - Search Engine used by DSpace
@@ -127,3 +127,6 @@ gem 'slim'
 
 # CUrl
 gem 'curb', '~> 0.8.8'
+
+# libArchive (Zip, Rar, ...)
+gem 'libarchive', '~> 0.1.2'
diff --git a/app/workers/thumbnail_generator_worker.rb b/app/workers/thumbnail_generator_worker.rb
index 75b809f3f6141524b8a98ee833ccf87476ebb84a..a9eb16364b825cdb3581c0109465d59b0a3e5963 100644
--- a/app/workers/thumbnail_generator_worker.rb
+++ b/app/workers/thumbnail_generator_worker.rb
@@ -1,58 +1,10 @@
 class ThumbnailGeneratorWorker
 
   include Sidekiq::Worker
-  include RepositoriesProxy
-  include Thumbnail::Creation
-  include Thumbnail::Formats
+  include Thumbnail::Generate
 
   def perform(learning_object_id)
-
-    item = learning_object_repository.find(learning_object_id)
-    filename = item.get_bitstream_filename_of "ORIGINAL"
-
-    size = "530x298"
-
-    unless accepted_formats.include? file_format filename
-      item.thumbnail = default_thumbnail
-    else
-      begin
-        retrieve_link = item.get_bitstream_retrievelink_of "ORIGINAL"
-        file = download_bitstream(retrieve_link,filename)
-      rescue
-        puts "ERROR!!! Some error occurred during file download."
-      else
-        item.thumbnail = generate_thumbnail(file,filename,size)
-        delete_downloaded_bitstream(file)
-      end
-    end
-
-    learning_object_repository.update_property(item,"thumbnail",item.thumbnail)
-
-  end
-
-  private
-
-  def delete_downloaded_bitstream(file)
-    File.unlink(file) if File.exist?(file)
-  end
-
-  def download_bitstream(url, filename)
-    output_dir = "/tmp"
-
-    output_file = "#{output_dir}/#{filename}"
-
-    c = Curl::Easy.new(url)
-    c.ssl_verify_peer = false
-    c.ssl_verify_host = false
-    File.open(output_file, 'wb') do |f|
-      # c.on_progress { |dl_total, dl_now, ul_total, ul_now|
-      #   puts "#{dl_total}, #{dl_now}, #{ul_total}, #{ul_now}"; true
-      # }
-      c.on_body {|data| f << data; data.size }
-      c.perform
-    end
-
-    return output_file
+    generate_thumbnail(learning_object_id)
   end
 
 end
diff --git a/lib/tasks/thumbnail.rake b/lib/tasks/thumbnail.rake
index 634ff332df43e82355d617274b2469b6a4f3c3c7..480b499107da08182184d6e92428cd84d22455c3 100644
--- a/lib/tasks/thumbnail.rake
+++ b/lib/tasks/thumbnail.rake
@@ -25,13 +25,16 @@ namespace :thumbnail do
         # Terminate loop if there are no more items to import
         break if items.empty?
 
-        # Increment offset, to get new items on next iteration
-        offset = offset + limit
-
         items.each do |item|
-          ThumbnailGeneratorWorker.perform_async(item.id)
+          if item.thumbnail.nil?
+            ThumbnailGeneratorWorker.perform_async(item.id)
+          elsif item.thumbnail.empty?
+            ThumbnailGeneratorWorker.perform_async(item.id)
+          end
         end
 
+        # Increment offset, to get new items on next iteration
+        offset += limit
       end
     end
   end
diff --git a/lib/thumbnail/formats.rb b/lib/thumbnail/accepted_formats.rb
similarity index 50%
rename from lib/thumbnail/formats.rb
rename to lib/thumbnail/accepted_formats.rb
index c7ac2c2aa9ed9c413070c934f4432d802d428fc6..bec7f427de5d0aea0ceba8a80ba69c471a4ab230 100644
--- a/lib/thumbnail/formats.rb
+++ b/lib/thumbnail/accepted_formats.rb
@@ -1,30 +1,53 @@
 module Thumbnail
-  module Formats
+  module AcceptedFormats
 
-    def file_format file
+    def get_file_basename file
       unless file.nil?
-        file_format = File.extname(file)
+        file_format = File.basename(file)
       else
         file_format = ""
       end
       file_format
     end
 
+    def get_file_extname file
+      unless file.nil?
+        file_name = File.extname(file)
+      else
+        file_name = ""
+      end
+      file_name
+    end
+
+    def array_to_upcase array
+      upcase_array = []
+      array.each do |a|
+        upcase_array << a.upcase
+      end
+      upcase_array
+    end
+
+    def accepted_archive_formats
+      lower = [".zip", ".gzip", ".bzip", ".tar"]
+      upper = array_to_upcase lower
+      return lower + upper
+    end
+
     def accepted_video_formats
       lower = [".mp4", ".wmv", ".3gp", ".asf", ".avi", ".flv", ".swf", ".mov", ".mpg", ".mpeg", ".rmvb", ".rm", ".vob", ".webm"]
-      upper = [".MP4", ".WMV", ".3GP", ".ASF", ".AVI", ".FLV", ".SWF", ".MOV", ".MPG", ".MPEG", ".RMVB", ".RM", ".VOB", ".WEBM"]
+      upper = array_to_upcase lower
       return lower + upper
     end
 
     def accepted_image_formats
       lower = [".jpg", ".jpeg", ".gif", ".png", ".bmp", ".tif", ".wmf"]
-      upper = [".JPG", ".JPEG", ".GIF", ".PNG", ".BMP", ".TIF", ".WMF"]
+      upper = array_to_upcase lower
       return lower + upper
     end
 
     def accepted_other_formats
       lower = [".pdf", ".pps"]
-      upper = [".PDF", ".PPS"]
+      upper = array_to_upcase lower
       return lower + upper
     end
 
diff --git a/lib/thumbnail/creation.rb b/lib/thumbnail/creation.rb
deleted file mode 100644
index aebc32bd9815aee17d1876640fabbb243828c838..0000000000000000000000000000000000000000
--- a/lib/thumbnail/creation.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-module Thumbnail
-  module Creation
-
-    include Formats
-
-    def generate_thumbnail(input, filename, size)
-      unless accepted_formats.include? file_format(filename)
-        return default_thumbnail
-      else
-        thumbnail = thumbnail_path(filename, size)
-        output = "#{root_dir}#{thumbnail}"
-        begin
-          if accepted_video_formats.include? File.extname(input)
-            generate_video_thumbnail(input, output, size)
-          else
-            generate_image_thumbnail(input, output, size)
-          end
-        rescue
-          return default_thumbnail
-        else
-          return thumbnail
-        end
-      end
-
-    end
-
-    def default_thumbnail
-      @default_thumbnail ||= nil
-    end
-
-    private
-
-    def generate_video_thumbnail(input,output,size)
-      movie = FFMPEG::Movie.new(input)
-      frame = (movie.duration * 25/100).floor
-      movie.screenshot(output,
-                        { seek_time: frame, resolution: size },
-                        preserve_aspect_ratio: :width)
-    end
-
-    def generate_image_thumbnail(input,output,size)
-      # Read the image and resize it. The `change_geometry' method
-      # computes the new image geometry and yields to a block. The
-      # return value of the block is the return value of the method.
-      img = Magick::Image.read(input)[0]
-      img.alpha(Magick::DeactivateAlphaChannel)
-      img.change_geometry!(size) { |cols, rows| img.thumbnail! cols, rows }
-      img.write(output)
-    end
-
-    def encode_hash_from(object)
-      Digest::SHA1.hexdigest object
-    end
-
-    def thumbnail_path(filename, size)
-      thumbnail_name = encode_hash_from filename
-      thumbnail_path = "#{thumbnails_dir}/#{thumbnail_name}_#{size}.jpg"
-    end
-
-    def thumbnails_dir
-      @thumbnails_dir ||= "/thumbnails"
-    end
-
-    def root_dir
-      @root_dir ||= Rails.root.join('public')
-    end
-
-  end
-end
diff --git a/lib/thumbnail/generate.rb b/lib/thumbnail/generate.rb
new file mode 100644
index 0000000000000000000000000000000000000000..8f2f59ca27fd43319d910ac22930d0e949ef9982
--- /dev/null
+++ b/lib/thumbnail/generate.rb
@@ -0,0 +1,211 @@
+module Thumbnail
+  module Generate
+
+    include AcceptedFormats
+    include RepositoriesProxy
+
+    def generate_thumbnail(learning_object_id)
+
+      size = "530x298"
+
+      item = learning_object_repository.find learning_object_id
+      return false if item.nil?
+
+      puts "[generate_thumbnail (#{item.id})] Starting to generate thumbnail for ID='#{item.id}'"
+
+      item_uniq_hash = encode_hash_from item.id.to_s + item.name
+
+      workdir = tmpdir_path(item_uniq_hash)
+      thumbnail = thumbnail_path(item_uniq_hash, size)
+      output = "#{root_dir}#{thumbnail}"
+
+      accepted_files = get_accepted_files(item,workdir)
+      accepted_files.sort! { |x,y| File.size(y) <=> File.size(x) }
+      accepted_files.each do |input|
+        filename = get_file_basename input
+        file_format = get_file_extname input
+        puts "[generate_thumbnail (#{item.id})] Trying to generate thumbnail for '#{filename}'"
+        begin
+          if accepted_video_formats.include? file_format
+            generate_video_thumbnail(input, output, size)
+          else
+            generate_image_thumbnail(input, output, size)
+          end
+        rescue Exception => e
+          puts "#{e}
+              \r[generate_thumbnail (#{item.id})] ERROR: input='#{input}'
+              \r[generate_thumbnail (#{item.id})] RESCUE: Try the next input.."
+        else
+          learning_object_repository.update_property(item,"thumbnail",thumbnail)
+
+          clean_tmpfiles(workdir, accepted_files)
+          puts "[generate_thumbnail (#{item.id})] SUCCESS: input='#{input}'"
+          return true
+        end
+      end
+
+      clean_tmpfiles(workdir, accepted_files)
+      puts "[generate_thumbnail (#{item.id})] ERROR: End of input files!!!"
+      return false
+
+    end
+
+    def default_thumbnail
+      @default_thumbnail ||= nil
+    end
+
+    private
+
+    def generate_video_thumbnail(input,output,size)
+      movie = FFMPEG::Movie.new(input)
+      if movie.valid? and !movie.video_codec.nil?
+        frame = (movie.duration * 25/100).floor
+        loop do
+          begin
+            movie.screenshot(output,
+                    { seek_time: frame, resolution: size },
+                    preserve_aspect_ratio: :width)
+          rescue
+            if frame > 0
+              puts "[generate_video_thumbnail] Decreasing frame and trying again!!! "
+              frame = (frame * 0.50).floor
+            else
+              raise "[generate_video_thumbnail] ERROR: Video's thumbnail was not generated. (FRAME_ERROR)"
+            end
+          else
+            return true, "[generate_video_thumbnail] Video's thumbnail was successfully generated!"
+          end
+        end
+      else
+        raise "[generate_video_thumbnail] ERROR: Video's thumbnail was not generated. (NULL_CODEC)"
+      end
+    end
+
+    def generate_image_thumbnail(input,output,size)
+      # Read the image and resize it. The `change_geometry' method
+      # computes the new image geometry and yields to a block. The
+      # return value of the block is the return value of the method.
+      img = Magick::Image.read(input)[0]
+      img.alpha(Magick::DeactivateAlphaChannel)
+      img.change_geometry!(size) { |cols, rows| img.thumbnail! cols, rows }
+      img.write(output)
+    end
+
+    def encode_hash_from(object)
+      Digest::SHA1.hexdigest object
+    end
+
+    def create_dir(dirname)
+      FileUtils.mkdir_p(dirname) unless File.directory?(dirname)
+    end
+
+    def tmpdir_path(id)
+      tmpdir = "/tmp/#{id}/"
+      create_dir tmpdir
+      return tmpdir
+    end
+
+    def thumbnail_path(id, size)
+      thumbnails_dir = "/thumbnails"
+      create_dir "#{root_dir}#{thumbnails_dir}"
+      return "#{thumbnails_dir}/#{id}_#{size}.jpg"
+    end
+
+    def root_dir
+      @root_dir ||= Rails.root.join('public')
+    end
+
+    def clean_tmpfiles(workdir,files)
+      files.each do |f|
+        delete_file f
+      end
+      delete_dir workdir
+    end
+
+    def delete_dir(dir)
+      FileUtils.rmdir(dir) if File.directory?(dir)
+    end
+
+    def delete_file(file)
+      FileUtils.rm(file) if File.exist?(file)
+    end
+
+    def get_accepted_files(item,workdir)
+
+      filename = item.get_filename
+      file_format = get_file_extname filename
+
+      accepted_files = []
+
+      if accepted_formats.include? file_format or accepted_archive_formats.include? file_format
+        begin
+          retrieve_link = item.get_retrievelink
+          file = workdir + filename
+          download_bitstream(retrieve_link,file)
+        rescue Exception => e
+          puts "#{e}"
+        else
+          if accepted_archive_formats.include? file_format
+            extract_accepted_files(file,workdir).each do |f|
+              accepted_files << f
+            end
+            delete_file file
+          else
+            accepted_files << file
+          end
+        end
+      end
+
+      return accepted_files
+    end
+
+    def extract_accepted_files(archive_file,workdir)
+
+      return [] if archive_file.nil?
+
+      extracted_files = []
+
+      puts "[extract_accepted_files] Extracting accepted files out from '#{get_file_basename(archive_file)}'"
+      Archive.read_open_filename(archive_file) do |archive|
+        while entry = archive.next_header
+          if accepted_formats.include? get_file_extname(entry.pathname)
+            filename = get_file_basename(entry.pathname)
+            file = workdir + filename
+            begin
+              File.open(file, 'wb') do |f|
+                archive.read_data(1024) do |d|
+                 f << d
+                end
+              end
+            rescue Exception => e
+              puts "#{e}
+                  \r[extract_accepted_files] ERROR: Some error occurred while extracting file '#{filename}'"
+            else
+              puts "[extract_accepted_files] SUCCESS: Extracted '#{filename}' to '#{file}'"
+              extracted_files << file
+            end
+          end
+        end
+      end
+
+      return extracted_files
+    end
+
+    def download_bitstream(url,output)
+      begin
+        c = Curl::Easy.new(url)
+        c.ssl_verify_peer = false
+        c.ssl_verify_host = false
+        File.open(output, 'wb') do |f|
+          c.on_body {|data| f << data; data.size }
+          c.perform
+        end
+      rescue
+        raise "[download_bitstream] ERROR: Some error occurred during file download."
+      else
+        return true
+      end
+    end
+
+  end
+end