Generating a PDF With Images from Base64 with Praw

2019-04-29 14:50发布

I am trying to save multiple pngs in one pdf. I'm receiving the PNGs from an API Call to the Endicia Label Server, which is giving me a Base64 Encoded Image as response.

Based on this Question:

How to convert base64 string to PNG using Prawn without saving on server in Rails

def batch_order_labels
  @orders = Spree::Order.ready_to_ship.limit(1)
  dt = Date.current.strftime("%d %b %Y ")
  title = "Labels - #{dt} - #{@orders.count} Orders"

  Prawn::Document.generate("#{title}.pdf") do |pdf|
    @orders.each do |order|
      label = order.generate_label
      if order.international?
        @image = label.response_body.scan(/<Image PartNumber=\"1\">([^<>]*)<\/Image>/imu).flatten.last
      else
        @image = label.image
      end

      file = Tempfile.new('labelimg', :encoding => 'utf-8')
      file.write Base64.decode64(@image)
      file.close


      pdf.image file
      pdf.start_new_page
    end
  end

  send_data("#{title}.pdf")
end

But I'm receiving following error:

"\x89" from ASCII-8BIT to UTF-8

Any Idea?

3条回答
成全新的幸福
2楼-- · 2019-04-29 15:05

you can't convert the Base64 to UTF-8. Leave it as plain ASCII:

  file = Tempfile.new('labelimg', :encoding => 'ascii-8bit')
  file.write Base64.decode64(@image)
  file.close

or even better - leave it as binary:

  file = Tempfile.new('labelimg')
  file.write Base64.decode64(@image)
  file.close

UTF-8 is multibite format and it's not usable for transferring binary data such as pics.

查看更多
小情绪 Triste *
3楼-- · 2019-04-29 15:10

There's no need to write the image data to a tempfile, Prawn::Document#image can accept a StringIO.

Try replacing this:

file = Tempfile.new('labelimg', :encoding => 'utf-8')
file.write Base64.decode64(@image)
file.close
pdf.image file

With this:

require 'stringio'
.....
image_data = StringIO.new( Base64.decode64(@image) )
pdf.image(image_data)
查看更多
萌系小妹纸
4楼-- · 2019-04-29 15:14

The Problem is, that the Api is returning this thing in UTF-8 - So I dont have a great choice. Anyhow, I found this solution to be working

  file = Tempfile.new('labelimg', :encoding => 'utf-8')
  File.open(file, 'wb') do |f|
    f.write Base64.decode64(@image)
  end
查看更多
登录 后发表回答