Skip to content

Instantly share code, notes, and snippets.

@zealot128
Last active September 18, 2023 11:18
Show Gist options
  • Save zealot128/5534cb70a06dcce96dba1fea7274fae5 to your computer and use it in GitHub Desktop.
Save zealot128/5534cb70a06dcce96dba1fea7274fae5 to your computer and use it in GitHub Desktop.
Activestorage Docx Previewer
# lib/activestorage_docx_previwer
module ActiveStorage
class Previewer::DocxPreviewer < Previewer
class << self
# also would be supported by unoconv
# "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/msword", "application/vnd.ms-powerpoint", "application/vnd.oasis.opendocument.text", "application/vnd.openxmlformats-officedocument.presentationml.presentation"
def accept?(blob)
blob.content_type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
end
end
def preview
download_blob_to_tempfile do |input|
draw_first_page_from input do |output|
yield io: output, filename: "#{blob.filename.base}.png", content_type: "image/png"
end
end
end
private
def draw_first_page_from(file, &block)
draw 'unoconv', '-f', 'pdf', '-e', 'PageRange=1', '--stdout', file.path do |output_pdf|
if File.size(output_pdf) > 0
make_image_from_pdf(output_pdf, &block)
end
end
end
def make_image_from_pdf(output_pdf, &block)
previewer = Rails.application.config.active_storage.previewers.find { |i|
i.accept?(OpenStruct.new(content_type: 'application/pdf'))
}
previewer.new(blob).send(:draw_first_page_from, output_pdf, &block)
end
end
end

Docx (and other Office doc) previewer support for ActiveStorage

Converts all document formats using LibreOffice first to PDF and then to an image, using build-in pdf previwer of ActiveStorage

  • needs: unoconv, a command line tool which uses libreoffice, e.g. apt install unoconv
  • needs a PDF converter, because libreoffice will make a pdf from the office document, Mupdf oder Poppler are already integrated into ActiveStorage, and poppler is free to use, e.g. apt install poppler-utils
# config/initializers/active_storage.rb
require 'activestorage_docx_previewer'
Rails.application.config.active_storage.previewers << ActiveStorage::Previewer::DocxPreviewer
@zealot128
Copy link
Author

Line 32 works only as: previewer.new(blob).send(:draw_first_page_from, output_pdf, &block)

That code is from a working Rails 5.2 app, I didn't test it with Rails 6 yet.
Yes, one has to pass a Blob, but just passing nil as that blob worked at least in the 5.2.

@durcak
Copy link

durcak commented Dec 4, 2019

yes on Rails 6.0.1 it needs blob, because pdf previewer calls blob.key in its implemetation

@sega
Copy link

sega commented May 29, 2020

@zealot128 Thanks for sharing!

@durcak Thanks for the Rails 6 fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment