Jack Collins
Jack Collins

Reputation: 1165

Save, store, and serve a user-uploaded PDF with Ruby on Rails

I've spent a ton of time digging into PDF tools with Ruby/Rails but I can't quite find what I need. There might be a gap in my understanding.

End User Workflow

As a user, I can upload a PDF document (likely a scanned image) to the AngularJS/Rails application. That PDF document should be stored as a PDF document on the server (not on cloud storage). Later, I can download that PDF document back to my computer.

First Attempt

I actually did get this working with CarrierWave, ImageMagick, and GhostScript. GhostScript was the missing piece of the puzzle that allowed ImageMagick to process the PDF. The code looked like this:

  def create
    @scanned_pdf = ScannedPdf.new
    @scanned_pdf.image = params[:file]
    image = MiniMagick::Image.new(@scanned_pdf.image.path)
    @scanned_pdf.content_type = image.mime_type
    @scanned_pdf.name = params[:file].original_filename

    if @scanned_pdf.save
      render status: :ok, json: serialize(@scanned_pdf)
    else
      render status: :unprocessable_entity, json: serialize_errors(@scanned_pdf)
    end
  end

Everything was all good until we realized we needed a commercial GhostScript license. We've contacted them and are having a bad experience with their sales team, so we are exploring other options.

Problem

I have been unable to take the data that comes in from params[:file] and save that as a PDF on the server. I don't even really know what format that data is in.

If I try the below code I end up with a file...

  # store_dir stores the path for the image

  FileUtils.mkdir @scanned_pdf.store_dir 
  FileUtils.cp_r params[:file].path, @scanned_pdf.store_dir

... but that file is filled with information like this:

iÀø³Ÿ/rÌKC̱>©¬êÚy0¢¯9äÛ1 Žoé^×}œœ_÷`ÿ~â•Rbu0ΞóC‚@J,LoŸ®MÀ IÃ:kˆ¾¿ªeßøîžÉ!Ç‚àh®6ˆÒ‡†î²jMÕñk¢{æv¸ A §NŸÁ×½á /=~"QÖ‡¤aj…*Åߘ‘†ƒXGøëÑ>ÀÏ\º‡V­IÓ/ˆ£Ç/M  E§ÉºN#OUÇËH¿&òƒáüÎøzÁ4kÖœ¤l«›hjªZ‡¡#øåù¡ ˜‚A­rPê0¬9ª:4j†²œÜ‘¦k6ôõÛráßè¿ÖaXsTuhÔ4 (ˆxxá"ï~z烎ùÖaXëTuhŒÚÂôöéiºÆ]ìÖaXëTuhÔ. iv

I am not even sure what I'm working with here.

I've experimented with the pdf-reader gem, active_pdftk, Wicked PDF, and many attempts at using Ruby File and IO classes myself.

Ideally, I would like to do something like

  File.open(params[:file].path, "rb") do |io|
    reader = PDF::Reader.new(io)
    rendered_pdf = reader.render # not actually a method
    rendered_pdf.save # in a useful location
  end

I feel like I'm missing something here, and I would really appreciate any insight you might have.

Upvotes: 3

Views: 1645

Answers (1)

Jack Collins
Jack Collins

Reputation: 1165

Well, I was able to make this work using only Ruby methods. Here is my code:

directory = FileUtils.mkdir @scanned_pdf.store_dir
path = File.join(directory, @scanned_pdf.name)
File.open(path, "wb") { |f| f.write(params[:file].read) }

I wasn't aware of the write method on the IO class. That was the missing piece of the puzzle.

Upvotes: 1

Related Questions