Picasa web uploader API

The Picasa Web Uploader (PWU) enables your end users to upload photos from Picasa to online services such as web-based email, blogging, gallery display, and photo printing services. With PWU, end users can interact with a dynamic web UI and preview images before sending photo data. PWU is a stateless API, which gives the developers and IT administrators the ability to control what images are uploaded (and at what sizes) via server settings. This API also supports uploads of video files.

As an example, Picasa uses the PWU with the BlogThis! feature.

Audience

This documentation is intended for programmers who want to enable end users to upload images from Picasa to a remote service. You should be familiar with Picasa, RSS and HTML. This documentation provides descriptions of the neccesary components of this technology and a reference of parameters that allow you to control how images are uploaded.

Components

    • Picasa - Google desktop software application

    • RSS feed - Data that describes what images should be uploaded

    • Localhost web server - Server on the end user's computer that provides access to images

    • Remote service - This is the service to which Picasa uploads images

Note - Consider using the JavaScript Detector to determine if Picasa 2.5 or later is installed and can accept PBZ files.

Overview

When the user clicks a custom button, Picasa generates an RSS 2.0 feed that describes the user's current selection (images in the Picasa tray). Picasa posts this feed to a service-specified URL and shows the resulting page in a Internet Explorer (IE) minibrowser in a Picasa window. At the same time, the remote service parses the RSS, and acknowledges the contents, usually displaying <img> tags using posted URLs (all refer to http://localhost...). Next, the remote service (or its JavaScript), adds special hidden form elements to a page that cause Picasa to upload files. On form submit, Picasa converts hidden image requests to record form elements in a multipart post and submits the entire form. All other items in the form are passed as well.

Picasa 2.1 exposes a localhost web server. This server can provide (localhost-only) access to images and thumbnails at arbitrary resolution. Picasa generates RSS 2.0 feeds based on a user's selection. Picasa hosts a minibrowser (hosted Internet Explorer), and can use it to display a remote UI. The browser is set to intercept certain kinds of posts, so it can simulate file-upload form fields currently in use for this purpose on many webpages.

Picasa requires a single URL to interact with your server. All relevant information is provided to a server in a single post. Your server can request that images be resized to arbitrary sizes on the client to save time. PWU replicates existing image-upload forms closely whenever possible.

Note - Services may request <100MB in a single post from a client. While it's possible request more than 100MB, it is possible that uploads larger than this will fail. Consider limiting the number or size of the photos requested.

PHP Sample

The following sample code illustrates the PWU. This sample runs on Apache with PHP installed. PHP needs write access to the install folder.

Geoff and Mike's Photoblog (6kb download, zip)

Warning - Do not install this demo code as-is on a public webserver. It does no authentication and allows any user to post files to your server.

Feeds, Formats, and Conventions

The PWU passes RSS to the remote server using a multipart section called "rss". Multipart does not form-encode the data, which makes reading and writing it easier. PWU uses:

    • The "title" field to indicate the original filename, and

    • The "description" field to describe user-entered or IPTC captions.

    • The RSS (2.0) feed uses the "pheed" extensions as detailed below. Media RSS is also supported.

Media RSS allows you to obtain original files (example: raw files) and processed files and you can request movies to be uploaded directly. However, you should check the type and only use the original link when you can process a file of a certain type.

Picasa sends JPEGs with all metadata preserved, including captions, geolocations, tags and applied edits. The following is a sample feed with multipart headers:

-----------------------------4984680A4EF1 Content-Disposition: form-data; name="rss" Content-Type: text/plain; charset=utf8 <?xml version="1.0" encoding="utf-8" ?> <rss version="2.0" xmlns:photo="http://www.pheed.com/pheed/" xmlns:media="http://search.yahoo.com/msrss/"> <clientlanguage>en</clientlanguage> <channel> <item> <title>DSC_8150.NEF</title> <photo:thumbnail>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/d2ce2a5c0e5674f4.jpg</photo:thumbnail> <photo:imgsrc>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/d2ce2a5c0e5674f4.jpg</photo:imgsrc> <media:group> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/d2ce2a5c0e5674f4.jpg" width="4320" height="2868" isDefault="true"/> <media:thumbnail url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/d2ce2a5c0e5674f4.jpg" width="144" height="96"/> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/original/d2ce2a5c0e5674f4" width="4320" height="2868" fileSize="12040782" type="image/x-image-raw"/> </media:group> </item> <item> <title>IMG_3121.JPG</title> <photo:thumbnail>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/3964710a7755ff0e.jpg</photo:thumbnail> <photo:imgsrc>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/3964710a7755ff0e.jpg</photo:imgsrc> <media:group> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/3964710a7755ff0e.jpg" width="4368" height="2912" isDefault="true"/> <media:thumbnail url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/3964710a7755ff0e.jpg" width="144" height="96"/> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/original/3964710a7755ff0e" width="4368" height="2912" fileSize="2510427" type="image/jpeg"/> </media:group> </item> <item> <title>IMG_3124.JPG</title> <photo:thumbnail>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/ae5db4fec743f1c8.jpg</photo:thumbnail> <photo:imgsrc>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/ae5db4fec743f1c8.jpg</photo:imgsrc> <media:group> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/ae5db4fec743f1c8.jpg" width="2912" height="4368" isDefault="true"/> <media:thumbnail url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/ae5db4fec743f1c8.jpg" width="96" height="144"/> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/original/ae5db4fec743f1c8" width="2912" height="4368" fileSize="2795099" type="image/jpeg"/> </media:group> </item> <item> <title>Experience.mpg</title> <photo:thumbnail>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/dca402d381b9c7f1.jpg</photo:thumbnail> <photo:imgsrc>http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/dca402d381b9c7f1.jpg</photo:imgsrc> <media:group> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/image/dca402d381b9c7f1.jpg" width="720" height="480" isDefault="true"/> <media:thumbnail url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/thumb/dca402d381b9c7f1.jpg" width="144" height="96"/> <media:content url="http://localhost:4249/09bfc952cdf1aff4b9d6ed642755061c/original/dca402d381b9c7f1" width="720" height="480" fileSize="69459972" type="video/mpeg"/> </media:group> </item> </channel> </rss> -----------------------------4984680A4EF1--

Note - Both the server port and the security token found in the URL are random, so you do not re-use this string across sessions.

Picasa RSS post sends <media:content> headers with the feed. This provides image width and height metadata, mime-type and access to the original file on disk. It also provides URLs via media:group for the following:

    • A processed JPEG at any size (default)

    • A thumbnail from our cache

    • An original unaltered file from disk (with mimetype)

Using this, Picasa can upload original files. In the type field, Picasa sends the following information for the original files:

    • .jpg - "image/jpeg"

    • .gif - "image/gif"

    • .bmp - "image/bmp"

    • .psd - "application/photoshop"

    • .avi - "video/x-msvideo"

    • .mov - "video/quicktime"

    • .mpg - "video/mpeg"

    • .wmv - "video/x-ms-wmv"

    • .asf - "video/x-ms-asf"

    • .tif - "image/tiff"

    • .png - "image/png"

    • raw formats (.cr2, .nef, .orf, etc.) - "image/x-image-raw"

The localhost image URLs use a size parameter, allowing the remote side a great deal of flexibility. You can use these parameters in an <img src> tag for inline display. Also, you can add hidden form elements to the page, which Picasa detects and uploads at the requested resolutions. For example, a service could request that Picasa generate thumbnails and screen-size images by making the following requests:

<input type=hidden name="http://localhost/image123.jpg?size=640"> <input type=hidden name="http://localhost/image123.jpg?size=128"> <input type=hidden name="http://localhost/image456.jpg?size=640"> <input type=hidden name="http://localhost/image456.jpg?size=128"> <input type=hidden name="http://localhost/image333.jpg?size=640"> <input type=hidden name="http://localhost/image333.jpg?size=128">

This example uploads three files, at two sizes each. The DOM "name" property specifies the image to upload. Picasa looks for these fields and rewrites them on the fly. Though it is seems obvious to put this data in the "value" field, the "name" is sent with a form post, so this syntax provides the names back in the post result, and can translate them appropriately.

From the above example, Picasa would convert the hidden elements to the equivalent of file-upload forms, replacing each request as follows:

-----------------------------0029482318BE Content-Disposition: form-data; name="http://localhost/image123.jpg?size=640"; filename="IMG_9457.JPG" Content-Type: image/jpeg [data] -----------------------------0029482318BE Content-Disposition: form-data; name="http://localhost/image123.jpg?size=128"; filename="IMG_9457.JPG" Content-Type: image/jpeg [data] -----------------------------0029482318BE Content-Disposition: form-data; name="http://localhost/image456.jpg?size=640"; filename="IMG_9458.JPG" Content-Type: image/jpeg [data] -----------------------------0029482318BE Content-Disposition: form-data; name="http://localhost/image456.jpg?size=128"; filename="IMG_9458.JPG" Content-Type: image/jpeg [data] -----------------------------0029482318BE Content-Disposition: form-data; name="http://localhost/image333.jpg?size=640"; filename="IMG_9459.JPG" Content-Type: image/jpeg [data] -----------------------------0029482318BE Content-Disposition: form-data; name="http://localhost/image333.jpg?size=128"; filename="IMG_9459.JPG" Content-Type: image/jpeg [data]

Ignore the URL "name" parameter when storing an image. The filename (which is derived from the user's machine) is appropriate when the service stores the image. Filenames may contain high-ascii characters, and they may collide (even within one post).

About the IE MinibrowserSince the IE minibrowser in Picasa has no navigation controls (see screenshot right), you should avoid linking to other parts of your site without opening another browser window. After you specify a particular URL in the button file:

    • If the user needs to navigate away from this page (e.g., to a sign in form), Picasa converts any navigation back to that page into the original POST that was provided, not a GET. For example, if Picasa knows about http://mysite.com/post, and that page redirects to http://mysite.com/login, the user ends up navigating back to http://mysite.com/post?sid=123456.

    • When the user navigates back, Picasa will POST the original data again to the original page.

Please only rely on this functionality only if neccesary, as it is is preferable for a service to store the original POST data or avoid navigation like this.

Receiving a Multi-Part Post

The remote service must do the following to receive a multi-part post:

    1. Receive each form-data item that's posted.

    2. Store an image based on "filename" and the JPEG content (don't use "name" at this stage).

    3. Generate a unique URL for the stored image.

    4. Replace all instances of "name" used by the service with the stored image's URL.

Response Codes

Since uploads via the above method do not affect the Picasa user interface (though they show a progress bar in the corner of the screen), response codes are simple. You should provide a result page for any successful post, because users won't receive feedback otherwise.

If you want Picasa to display a webpage (a result page, an error page, etc.) after the upload completes, specify the URL in a typical HTTP body (MIME type is ignored, but text/plain would work) to show as the result of the POST above. Please note that this result page appears in the user's default browser (whereas the the remote UI appears in Internet Explorer), so you must pass any session information in the URL.

Do not use a redirect for a response, but use a 200 ("200 Ok") page that provides a URL in the body of the HTML. If you provide a redirect, Picasa reads the response from the redirected URL, but we will not display a browser window automatically.

Uploading Using Picasa's Button Toolbar

Picasa has a format for adding buttons and letting the user choose where they go. Read the Picasa Button API documentation to learn more.