PDF created with phantomjs seems to use ASCII

104 Views Asked by At

A am running an application in Meteor on Galaxy. I use phantomjs to generate a PDF-file from an HTML string. When I print the HTML-string in the console, all characters appear correct, but the rendered PDF shows Chinese characters as if it were using ASCII encoding. Examples: "骆高" → "éªé«" and "TÜV" → "TÃV".

Logs of the data/html looks fine here:

  • generatePdf method
  • @html in constructor
  • child.stdin.write args

I tried the following, to no avail:

  • Added <meta charset="utf-8" /> to the HTML
  • Added <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
  • Set encoding for phantomjs: phantom.outputEncoding = 'utf8
  • Set encoding for child_process: child.stdin.setEncoding('utf8')
  • Set encoding for child_process: child.stdout.setEncoding('utf8')
  • Set encoding when writing file to S3 Bucket: Body: new Buffer buffer, 'utf8'

Versions used:

  • Meteor: 1.10.2
  • phantomjs: 1.9.8

methods.coffee

Meteor.methods
   generatePdf: () ->
      # gather data from database
      data.html = SSR.render('pdfTemplate', data)
      Meteor.wrapAsync(createPdf)(data)

createPdf = (data,callback) ->
   pdf = new PDF data.html, data.options
   pdf.toFile (err, output) ->
      if output
         body = fs.createReadStream(output.filepath).pipe(zlib.createGzip())
         fs.readFile output.filepath, (err,buffer) ->
            return callback(err) if err
            fs.unlink output.filepath, (err) ->
               return callback(err) if err
               s3.putObject
                  Bucket: "<Bucket>"
                  Key: "<Key>"
                  Body: new Buffer buffer
                  ContentType: 'application/pdf'

pdf.coffee

fs = Npm.require('fs')
Stream = Npm.require('stream').Readable
childprocess = Npm.require('child_process')
path = Npm.require('path')
assert = Npm.require('assert')

phantomjs = Npm.require('phantomjs')

class PDF
   constructor: (@html, @options={}) ->
      pageScript = @options.script or 'pdf_a4_portrait.js'
      @script = path.join(Meteor.rootPath, 'assets/packages/fta_phantomjs/scripts', pageScript)
      @options.directory = process.env.TMPDIR
      @options.phantomArgs ?= []
      assert(typeof @html is 'string' && @html.length, "html-pdf: Can't create a pdf without an html string")
      @options.timeout = parseInt(@options.timeout) || 30000

   toFile: (callback) ->
      child = childprocess.spawn('phantomjs', [].concat(@options.phantomArgs, [@script]))
      stdout = []
      stderr = []

      timeout = setTimeout ->
         child.stdin.end()
         child.kill()
         stderr = [new Buffer('html-pdf: PDF generation timeout. Phantom.js script did not exit.')] unless stderr.length
      , @options.timeout

      child.stdout.on 'data', (buffer) ->
         stdout.push(buffer)

      child.stderr.on 'data', (buffer) ->
         stderr.push(buffer)
         child.stdin.end()
         child.kill()

      child.on 'exit', (code) ->
         clearTimeout(timeout)
         if code || stderr.length
            err = new Error(Buffer.concat(stderr).toString() or 'html-pdf: Unknown Error')
            return callback(err)
         else
            try
               data = Buffer.concat(stdout).toString()?.trim()
               data = JSON.parse(data)
               return callback(null, data)
            catch err
               return callback(err)
      args = JSON.stringify({@html, @options})+'\n'
      child.stdin.write(args, 'utf8')
0

There are 0 best solutions below