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')