Skip to content
This repository has been archived by the owner on May 30, 2023. It is now read-only.

PhantomJS 2.0 webserver module response.setEncoding("binary") not working #13026

Closed
leoweigand opened this issue Feb 24, 2015 · 15 comments
Closed
Assignees

Comments

@leoweigand
Copy link

In phantomjs 2.0, calling setEncoding("binary") on the response object has no effect. What was working fine with version 1.9.7_1 now seems to be broken.
Code to replicate (where test.pdf may be any other binary file in the directory of the script):

var server  = require('webserver').create(),
        fs  = require('fs');

server.listen(8000, function(request, response) {
    response.statusCode = 200;
    response.setHeader('Content-type', 'application/pdf')
    response.setEncoding('binary');

    response.write( fs.read('test.pdf', 'b') );
    response.close();   
});

I am running on Mac OSX 10.10.

@ghost
Copy link

ghost commented Mar 30, 2015

I can also confirm that this is true. Multiple hours were spent wondering why examples wouldn't work so thank you @lweigand :D. Works fine on 1.9.8 on Windows.

@Verikon
Copy link

Verikon commented May 4, 2015

Confirmed this is broken. (ubuntu, compiled Phantom2 from source).

@GoldHornKing
Copy link

Confirmed in windows. It worked with version 1.9.8.

The pdf file downloaded from response cannot be opened, Adobe Reader says it is damaged.

I also found version 2.0 generates large PDF than 1.9.8 for same page.

@smalltalking
Copy link

It looks like the content is encoded to UTF-8 - something that doesn't happen with 1.9.7 - then it gets truncated to the length before the encoding, so the end of the file is lost.

@griffinmyers
Copy link

+1 big bummer

@jigfox
Copy link

jigfox commented Jul 15, 2015

confirmed on mac, too

downgrading to phantomjs 1.9.8 helped solving this issue

@marcosbrigante
Copy link

Same here. Any workarounds to avoid downgrading?

@griffinmyers
Copy link

@marcosbrigante we pushed the encoding down into the client, i.e. in the response handler from phantom did something like this:

 var binaryString = new Buffer(response).toString('utf-8');
 return new Buffer(binaryString, 'binary');

@marcosbrigante
Copy link

@griffinmyers thanks I will give it a try. My current workaround is to use base64 instead of binary to transfer the pdf. But it requires decoding on the client...

response.setHeader('Content-type', 'application/base64');
response.write(btoa(fs.read('test.pdf', 'b')));

@vitallium vitallium added this to the Release 2.0.1 milestone Jul 30, 2015
@vitallium vitallium self-assigned this Jul 30, 2015
vitallium added a commit to vitallium/phantomjs that referenced this issue Aug 2, 2015
QVariantHelper expects body to be the same type as before conversion.
If target type doesn't match the source type, QVariantHelper will return 0.
We can't convert in this way: QString > QVariant -> QByteArray
Instead we must use the following way: QString > QVariant -> QString

Fixes: ariya#13026
vitallium added a commit to vitallium/phantomjs that referenced this issue Aug 6, 2015
QVariantHelper expects body to be the same type as before conversion.
If target type doesn't match the source type, QVariantHelper will return 0.
We can't convert in this way: QString > QVariant -> QByteArray
Instead we must use the following way: QString > QVariant -> QString

Fixes: ariya#13026
@GoldHornKing
Copy link

For anyone still stuck here, please try this work around. Thanks for @marcosbrigante and all other posts.

PhantomJS script:

var pdfStream = fs.open(fileLocation, 'rb'); 
var pdfContent = pdfStream.read();              
var base64Encoded = btoa(pdfContent);
response.statusCode = 200;
response.headers = {
                'Cache': 'no-cache',
                'Content-Type': 'application/base64',
                'Connection': 'Keep-Alive',
                'Content-Length': base64Encoded.length.toString()
                };
response.write(base64Encoded);
response.close();

Server side [C#]:

HttpWebResponse response =     (HttpWebResponse)httpWReq.GetResponse();
using (Stream stream = response.GetResponseStream())
{
    using (StreamReader readStream = new StreamReader(stream))
    {
        string base64String = readStream.ReadToEnd();
        byte[] decodedArray = Convert.FromBase64String(base64String);

        // The following three lines are testing if content is a valid pdf
        using (FileStream stream1 = System.IO.File.Create("c:\\test.pdf"))
        {
            stream1.Write(decodedArray, 0, decodedArray.Length);
        }
        return decodedArray;
}

//decodedArray could be then added in a  HttpRequest

@jigfox
Copy link

jigfox commented Oct 11, 2015

Is there a timeline, when this will be released?

vitallium added a commit to vitallium/phantomjs that referenced this issue Oct 20, 2015
QVariantHelper expects body to be the same type as before conversion.
If target type doesn't match the source type, QVariantHelper will return 0.
We can't convert in this way: QString > QVariant -> QByteArray
Instead we must use the following way: QString > QVariant -> QString

Fixes: ariya#13026
@zackw zackw modified the milestones: Release 2.0.1, Release 2.1 Dec 23, 2015
@rcarmo
Copy link

rcarmo commented Jan 24, 2016

I'm still having trouble with this, even with 2.1. Is that ".toLatin()" conversion right?

@vitallium
Copy link
Collaborator

@rcarmo yes. It works. Just tested it.

@rcarmo
Copy link

rcarmo commented Jan 24, 2016

for me, this:

res.setEncoding('binary');
res.write(fs.open(path,'rb').read());
res.close();

Is still failing under 2.1. Trying to figure out why the webserver doesn't like it...

@kkeybbs
Copy link

kkeybbs commented Jan 25, 2016

In an old version(2.0.0-windows), setEncoding('binary') doesn't work.but rsp.setEncoding('latin1') works.

I update to the 2.1.1-windows, setEncoding('binary') works too.

So you can use setEncoding('latin1') if you don't want to update at once.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests