Saturday, June 30, 2012

Google Cloud Print with the Zend Framework

This is a quick tutorial on how to use Google Cloud Print from PHP under the Zend Framework. Parts of this are based on other online tutorials (including Mimeo's tutorial). See also https://developers.google.com/cloud-print/docs/overview

First, we need to get a cloud printer set up. Follow the directions here: http://support.google.com/cloudprint/bin/answer.py?&answer=1686197

Now, we need to determine the GUID of the cloud printer you set up. The following code will query the cloudprint service and dump the results of the "search" command:

<?

require_once 'Zend/Loader/Autoloader.php';

$autoloader = Zend_Loader_Autoloader::getInstance();

$username = 'username@gmail.com';
$password = 'password';

$client = Zend_Gdata_ClientLogin::getHttpClient($username, $password, 'cloudprint');

// Get token, add headers, set uri
$Client_Login_Token = $client->getClientLoginToken();
$client->setHeaders('Authorization','GoogleLogin auth='.$Client_Login_Token);
$client->setUri('http://www.google.com/cloudprint/interface/search');

$response = $client->request(Zend_Http_Client::POST);

$PrinterResponse = json_decode($response->getBody());

if (isset($PrinterResponse->printers)) {
    foreach ($PrinterResponse->printers as $printer) {
        echo ("{$printer->id}\t{$printer->name}\r\n");
    }
} else {
    echo "Something went wrong!\r\n";
    print_r($PrinterResponse);
}


?>

The output (from command line) will look something like this:

4d267d11-4135-0710-d0b2-18aacfeff12d Microsoft XPS Document Writer
__google__docs Save to Google Docs
1c2ea9f6-2b17-0cc4-507f-b59cf1592763 Fax
390272cc-fe27-b4fe-c60f-eba7db8c6b63 Send To OneNote 2007

The printer that I'll be using for this tutorial is the first one, "Microsoft XPS Document Writer". Locate your printer in the output, and make a note of the GUID (e.g. 4d267d11-4135-0710-d0b2-18aacfeff12d

For my purposes, I did not need to print PDFs to cloud print, I needed to print some existing html-based reports. To get HTML in to a format that cloud print would accept, I used the DOMPDF library.

DOMPDF comes with its own autoloader, but it can easily be made to work with Zend's autoloader:


require_once('path/to/dompdf/dompdf_config.inc.php');


$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->pushAutoloader('DOMPDF_autoload','');


Once DOMPDF is set up, we can create a PDF from some HTML:


$dompdf = new DOMPDF();
$dompdf->load_html('<html><body><b>Hello, Google Cloud Print!</b></body></html>');
$dompdf->render();
$data = $dompdf->output();


Cloud Print current supports content types of url, application/pdf, image/jpeg, and image/png. For the URL type, the resource you reference must be a pdf, jpeg, or png. If you already have your data in one of these three formats, you don't need to bother with DOMPDF.

Here is the complete example, which renders some HTML to a PDF and sends it to Google Cloud Print:


<?

// Configuration

$username = 'username@gmail.com';
$password = 'password';
$printerid = '4d267d11-4135-0710-d0b2-18aacfeff12d';
$jobtitle = 'Description of the print job';


// Autoloader
require_once 'Zend/Loader/Autoloader.php';
require_once('/path/to/dompdf/dompdf_config.inc.php');

$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->pushAutoloader('DOMPDF_autoload','');

// HTML to PDF
$dompdf = new DOMPDF();
$dompdf->load_html('<html><body><b>Hello, Google Cloud Print!</b></body></html>');
$dompdf->render();
$data = $dompdf->output();

// Set up Gdata client and log in
$client = \Zend_Gdata_ClientLogin::getHttpClient($username, $password, 'cloudprint');
$Client_Login_Token = $client->getClientLoginToken();
$client->setHeaders('Authorization','GoogleLogin auth='.$Client_Login_Token);
$client->setUri('http://www.google.com/cloudprint/interface/submit');

// Set parameters
$client->setParameterPost('printerid',$printerid);
$client->setParameterPost('title', $jobtitle);
$client->setParameterPost('contentTransferEncoding','base64');
$client->setParameterPost('content',base64_encode($data));
$client->setParameterPost('contentType','application/pdf');

// Submit and get response
$response = $client->request(\Zend_Http_Client::POST);

// Check response
$PrinterResponse = json_decode($response->getBody());

if (isset($PrinterResponse->success) && $PrinterResponse->success==1) {
    echo "Success! The document should print shortly.\r\n";
} else {
    echo "Failure!\r\n";
    print_r($PrinterResponse);
}


?>

On my setup, when I execute this, after a few seconds a "Save the file as" dialog appears on the Windows computer that I configured the XPS Document Writer on. Saving the file and opening it, I see the following:



8 comments:

  1. I am trying to find something just like this...but without the dependencies on special libraries (such as Zend). I already generate the files just fine...so i am just looking for a method to send them to a GCP printer. Any chance you have run across a standalone version anywhere?

    ReplyDelete
    Replies
    1. I'm certain that I have, although I can't seem to find it doing some quick google searches. Submitting the job should be simple enough, it's the auth portion that I'm not sure about. Let me know if you do find something, if I have some free time soon I'll see about throwing together an example that doesn't have any framework dependencies.

      Delete
  2. It will be nice to have some code examples on how to register a printer, especially when I have multiple printers how can I pick the one I want to share.

    ReplyDelete
    Replies
    1. The registration happens via Chrome, I don't believe that you can programmatically register new printers at this time. From the gear/lines menu in Chrome, select Settings, then Advanced Settings, and there should be a Google Cloud Print section. From there you can add printers.

      The first code snippet in my post shows how to get the list of all cloud printers and their ids for a particular account. From there you could display the list to the user of your application, and let them select which printer they'd like to use.

      Delete
  3. This worked so great! Thank you!

    One thing to note is that Google now requires "https" to use some of the functions including /submit.

    ReplyDelete
    Replies
    1. I'm so glad that this was helpful. Thanks for the note about https, I need to update the examples soon. Too many things to do, not enough time! :)

      Delete
  4. Which Zend version did you use? Thanks

    ReplyDelete
    Replies
    1. This was using 1.x, I haven't made the switch to 2.x yet.

      Delete