node.jspdfgoogle-cloud-printunirest

Google Cloud Print API - white page when printing PDF


I want to send a PDF file to be printed using the Google Cloud Print API. The code bellow will give me a positive message telling me that one page was generate. When I go and check what came out, I gate an empty page.

The same result happens if I save the print on Google Drive.

The code

unirest.post('https://www.google.com/cloudprint/submit')
.header('Authorization', 'Bearer ' + token)
.header("Accept-Charset", "utf-8")
.field('xsrf', xsrf_token)
.field('printerid', printerId)
.field('ticket', '{"version": "1.0", "print": {}}')
.field('title', 'Test from Simpe.li')
.field('contentType', 'application/pdf')
.attach('content', buffer)
.end(function (res) {

    console.log(res);

});

I know that what I'm sending is a PDF, because when I change the

.field('contentType', 'application/pdf')

to

.field('contentType', 'text/plain')

I will get 53 pages of text which is the raw content of the PDF file.

enter image description here

Question

What I'm doing wrong?

Tech spec


Solution

  • It turns out that the Google documentation left some key information out. To send a binary type data, like a PDF, you need to convert the file to base64. In addition to that you need to tell Google that you are going to send them a base64 blob with the add field contentTransferEncoding and set the value to base64.

    Another important thing. There is a bug in Unirest (for NodeJS at least), where sending a base64 file won't set the Content-Size header. Nor even setting your own will fix the problem. To circumvent this issue I had to switch to Request. The following code shows a post to Google Cloud Print that works:

    let buffer64 = buffer.toString('base64');
    
    let formData = {
        xsrf: xsrf_token,
        printerid: printerId,
        ticket: '{"version": "1.0"}',
        title: 'Test Print',
        contentTransferEncoding: 'base64',
        contentType: 'application/pdf',
        content: buffer64
    };
    
    let headersData = {
        'Authorization': 'Bearer ' + token
    };
    
    request.post({
        url: 'https://www.google.com/cloudprint/submit',
        headers: headersData,
        formData: formData
    }, function (err, httpResponse, body) {
    
      if (err) {
    
        return console.error('upload failed:', err);
    
      }
    
      console.log('Upload successful!  Server responded with:', body);
    
    });
    

    I hope this will help others :)