级别: 中级 Vikram Vaswani, 创始人, Melonfire
2008 年 12 月 15 日 Picasa Web Albums 为 Web 应用程序开发人员提供了一种基于 REST 的
Data API,可用于处理存储于服务器上的照片和相册。PHP 的 SimpleXML
扩展和 Zend 的 GData Library 则非常适合于处理由此 API 生成的 XML 提要,借助于此,您就能够定制照片管理和共享的 PHP 应用程序。通过本文,了解这个 Picasa Web Albums Data API,看看如何能够用它来检索照片和照片元数据;添加、修改和删除照片;执行 Picasa 用户生成内容的关键字搜索。
简介
 |
常用缩写词
- API:应用程序编程接口
- HTTP:超文本传输协议
- MIME:多用途因特网邮件扩展协议
- PHP:PHP 超文本预处理程序
- REST:具象状态传输
- URL:统一资源定位符
- XML:可扩展标记语言
|
|
正如喜欢拍摄大量数字照片的人一样,我也经常碰到磁盘混乱的问题 — 旧照片占据了我计算机上数百兆字节的空间,这些照片只粗略进行了标记,有的甚至都没有标记。几个月前,在我尝试了 Google 免费的 Picasa 照片管理软件之后,才从混乱中找出了处理办法。
Picasa 不仅可以从 Web 上下载 — 它还能通过免费的照片共享网站 Picasa Web Albums 在线使用。在这个网站,用户可以上传照片和视频,将这些照片和视频分门别类地放入相册、用关键字标记这些照片和视频以便于搜索、与他人共享这些照片和视频。不过,最棒的还在幕后:与很多其他的 Google 工具一样,Picasa Web
Albums 公开了一个 Data API,允许开发人员围绕在用户相册内存储的照片构建定制应用程序。您可以访问这个 API,它遵循 REST 模型。此 API 还具备针对很多常用语言(包括我最常使用的 PHP)的客户库。
本文将向您介绍 Google Picasa Web Albums Data API 并向您展示如何集成 PHP 应用程序和 Picasa 相册和照片。本文的示例包括如何检索相册和照片、通过定制的 Web 界面上传照片并按关键字搜索照片。现在,就请您加入进来,让我们立即开始吧!
Picasa Web Albums Data API 简介
在深入研究 PHP 代码之前,先来简单介绍 Picasa Web Albums Data
API。与所有基于 REST 的服务一样,先要有一个对指定服务的 HTTP 请求。这个 HTTP 请求包含具有一个或多个输入参数的查询;服务器用 Atom 或 RSS 格式的响应(或提要)回复此查询,这类格式适合于在任何支持 XML 的客户机内解析。
一个典型的 Picasa 提要包含很多信息。举例来说,试着在浏览器中弹出 URL http://picasaweb.google.com/data/feed/api/user/userid?kind=photo into(在用您的 Google 帐户用户名替换了 userid 之后)并假设在 Picasa Web Albums 内已经保存了一些照片和相册,输出结果应该类似 清单 1。
遍览上述输出以熟悉其中的主要元素:
- Picasa Web Albums Data API 用具有所需数据的提要响应 REST 请求。可用的提要有很多种:相册提要、照片提要、用户提要、用户联系提要等。不过,在很多情况下,XML 响应都会包含一个 <feed> 元素作为根元素。<feed> 元素又包含 <link> 元素(包含结果集当前页、后一页和前一页)和 <openSearch:> 元素(包含此搜索的汇总统计数据)。
- 最外边的 <feed> 元素包含一个或多个 <entry> 元素,每个 <entry> 元素代表与查询相匹配的每个照片,而且还包含所代表照片的进一步信息,包括它的标题、文件名、发布日期以及作者。每个 <entry> 又包含 <link> 元素,它提供 URL 链接以查看和编辑此照片。
- 每个 <entry> 内的一组 <gphoto:> 元素包含有关此照片的详细信息:大小、尺寸、相册、注释数量等。
- 每个 <entry> 内的 <media:group> 元素包含照片的关键字和缩略图链接??
用 SimpleXML 检索照片
现在,我们来看看一个用 PHP
和 SimpleXML 解析 Picasa Web Albums 提要的例子。清单 2 接受 清单 1 的提要并使用 SimpleXML 从中提取相关的数据段并将其格式化成 Web 页:
清单 2:用 SimpleXML 检索照片列表
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Listing album contents</title>
<style>
body {
font-family: Verdana;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
img {
float: left;
}
</style>
</head>
<body>
<?php
$userid = 'userid%40googlemail.com';
// build feed URL
$feedURL = "http://picasaweb.google.com/data/feed/api/user/$userid?kind=photo";
// read feed into SimpleXML object
$sxml = simplexml_load_file($feedURL);
// get album name and number of photos
$counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
$total = $counts->totalResults;
?>
<h1><?php echo $sxml->title; ?></h1>
<?php echo $total; ?> photo(s) found.
<p/>
<?php
// iterate over entries in album
// print each entry's title, size, dimensions, tags, and thumbnail image
foreach ($sxml->entry as $entry) {
$title = $entry->title;
$summary = $entry->summary;
$gphoto = $entry->children('http://schemas.google.com/photos/2007');
$size = $gphoto->size;
$height = $gphoto->height;
$width = $gphoto->width;
$media = $entry->children('http://search.yahoo.com/mrss/');
$thumbnail = $media->group->thumbnail[1];
$tags = $media->group->keywords;
echo "<h2>$summary</h2>\n";
echo "<table><tr><td><img src=\"" .
$thumbnail->attributes()->{'url'} . "\"/></td>\n";
echo "<td><span class=\"attr\">File</span>: $title
<br />\n";
echo "<span class=\"attr\">Size</span>: $size bytes
($height x $width) <br />\n";
echo "<span class=\"attr\">Tags</span>: $tags
</td></tr></table>\n";
}
?>
</body>
</html>
|
图 1 展示了输出结果:
图 1. 列出照片的 Web 页
清单 2 先是使用 simplexml_load_file() 对象向提要 URL 发送一个请求并将响应转变为一个 SimpleXML 对象。之后,它对此响应内的全部 <entry> 进行迭代,用 foreach() 循环对每一个进行处理并检索信息,如 图 1 所示。每个 <entry> 下的子节点由 SimpleXML 对象属性表示 — 比如,<title> 节点由 $entry->title 表示,<summary> 节点由 $entry->summary 表示,以此类推。关键字和缩略图图像则从每个 <entry> 下的 <media:group> 元素中获得。
处理用户和相册提要
如果想要获得由某个特定用户创建的全部相册的列表,也很容易实现。可以使用 清单 2 中的那个提要 URL,但是要将类型参数从照片改为相册。清单 3 展示了如何获得和解析这样的一个提要:
清单 3:用 SimpleXML 检索相册列表
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Listing albums</title>
<style>
body {
font-family: Verdana;
}
</style>
</head>
<body>
<h1>Album Listing</h2>
<?php
$userid = 'userid%40googlemail.com';
// build feed URL
$feedURL = "http://picasaweb.google.com/data/feed/api/user/$userid?kind=album";
// read feed into SimpleXML object
$sxml = simplexml_load_file($feedURL);
// get album names and number of photos in each
echo "<ul>";
foreach ($sxml->entry as $entry) {
$title = $entry->title;
$gphoto = $entry->children('http://schemas.google.com/photos/2007');
$numphotos = $gphoto->numphotos;
echo "<li>$title - $numphotos photo(s)</li>\n";
}
echo "</ul>";
?>
</body>
</html>
|
图 2 展示了修改后的输出结果:
图 2. 列出相册的 Web 页
要获得一个其中只列出此特定相册内的照片的相册提要,只需在这个提要 URL 内指定相册名称。清单 4 展示了如何获得和解析这样的一个提要:
清单 4:用 SimpleXML 检索某个相册内的照片
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Listing album contents</title>
<style>
body {
font-family: Verdana;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
img {
float: left;
}
</style>
</head>
<body>
<?php
$userid = 'userid%40googlemail.com';
$album = 'France2008';
// build feed URL
$feedURL = "http://picasaweb.google.com/data/feed/api/user/$userid/album/$album";
// read feed into SimpleXML object
$sxml = simplexml_load_file($feedURL);
// get album name and number of photos
$counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
$total = $counts->totalResults;
?>
<h1><?php echo $sxml->title; ?></h1>
<?php echo $total; ?> photo(s) found.
<p/>
<?php
// iterate over entries in album
// print each entry's title, size, dimensions, tags, and thumbnail image
foreach ($sxml->entry as $entry) {
$title = $entry->title;
$summary = $entry->summary;
$gphoto = $entry->children('http://schemas.google.com/photos/2007');
$size = $gphoto->size;
$height = $gphoto->height;
$width = $gphoto->width;
$media = $entry->children('http://search.yahoo.com/mrss/');
$thumbnail = $media->group->thumbnail[1];
$tags = $media->group->keywords;
echo "<h2>$summary</h2>\n";
echo "<table><tr><td><img src=\"" .
$thumbnail->attributes()->{'url'} . "\"/></td>\n";
echo "<td><span class=\"attr\">File</span>: $title
<br />\n";
echo "<span class=\"attr\">Size</span>: $size bytes
($height x $width) <br />\n";
echo "<span class=\"attr\">Tags</span>: $tags
</td></tr></table>\n";
}
?>
</body>
</html>
|
And 图 3 展示了输出的效果:
图 3. 列出相册内的照片的 Web 页
用 Zend GData Client Library 检索照片
前一个例子展示了利用 PHP 从 Picasa Web Albums 读取和使用数据是多么地容易。但是,只读访问有其局限性。要执行需要写访问的更复杂的操作,比如添加照片或相册,就需要向应用程序中添加用户身份验证,而这要借助于 Google 认可的两种验证方法之一:AuthSub 或 ClientLogin。
要手动执行这类身份验证是件非常麻烦的事情,需要大量代码来应对一个典型的身份验证过程中可能出现的各种情况。幸运的是,您不必为此费心:Zend 的 GData Client Library 可以帮您处理所有细节,它专门为想要集成 PHP 应用程序和 Google Data API 的开发人员设计。这个库可以单独下载(相关链接,请参见 参考资料),它提供了针对 Google Data API 的一个面向对象的方便接口,并封装了大多数的常见任务(包括身份验证),这样一来,您就可以着重处理应用程序的核心功能了。
清单 5 用 Zend GData Client Library 重复实现了 清单 4 的功能:
清单 5:用 Zend GData Client Library 检索相册内的照片
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Listing album contents</title>
<style>
body {
font-family: Verdana;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
img {
float: left;
}
</style>
</head>
<body>
<?php
// load library
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');
// create authenticated HTTP client for Picasa service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid_cnnew1@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);
// generate query to get album feed
$query = $gphoto->newAlbumQuery();
$query->setUser("default");
$query->setAlbumName("France2008");
// get and parse album feed
// get album name and number of photos
try {
$feed = $gphoto->getAlbumFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getResponse();
}
?>
<h1><?php echo $feed->getTitle(); ?></h1>
<?php echo $feed->getTotalResults(); ?> photo(s) found.
<p/>
<?php
// process each photo entry
// print each entry's title, size, dimensions, tags, and thumbnail image
foreach ($feed as $entry) {
$title = $entry->getTitle();
$summary = $entry->getSummary();
$thumbnail = $entry->getMediaGroup()->getThumbnail();
$tags = $entry->getMediaGroup()->getKeywords();
$size = $entry->getGphotoSize();
$height = $entry->getGphotoHeight();
$width = $entry->getGphotoWidth();
echo "<h2>$summary</h2>\n";
echo "<table><tr><td><img src=\"" .
$thumbnail[1]->url . "\"/></td>\n";
echo "<td><span class=\"attr\">File</span>: $title
<br />\n";
echo "<span class=\"attr\">Size</span>: $size bytes
($height x $width) <br />\n";
echo "<span class=\"attr\">Tags</span>: $tags
</td></tr></table>\n";
}
?>
</body>
</html>
|
清单 5 先是加载 Zend 类库,然后初始化 Zend_Http_Client 类的一个实例。为此客户提供所需的用户身份验证信息,并打开到 Picasa 服务的一个验证过的连接。一旦这个验证过的连接打开,getAlbumFeed() 方法就会被用来检索此相册提要。此方法接受一个 AlbumQuery 对象,此对象由如下两个参数配置:
对 getAlbumFeed() API 调用的响应是一个 XML 提要,这个提要类似于 清单 1 中的那个,并随后被解析和转换成一个 PHP 对象。此对象公开 getter 和 setter 方法,这就让通过对象/属性注释从 XML 提要内的节点检索特定的信息块变得十分容易。例如,getSummary() 方法检索照片汇总,而 getGphotoSize() 方法则检索以字节为单位的照片大小。
图 4 展示了输出结果:
图 4. 列出相册内照片的 Web 页
添加新照片
除了列出照片之外,添加新照片又如何实现呢?同样非常简单。
要添加新照片,只需以一个 MIME 编码的块向此相册提要 URL POST 这个图像文件以及相关的元数据。此块的一个部分应该包含以 XML 编码的 <entry>,另一个部分应该包含二进制数据。清单 6 展示了这类块:
清单 6:用元数据添加新照片的一个 POST 包示例
--=_00fb9c5957c74e05312cbc2f9d1d09b8
Content-Type: application/atom+xml
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom">
<atom:category term="http://schemas.google.com/photos/2007#photo"
scheme="http://schemas.google.com/g/2005#kind"/>
<atom:summary type="text">Notre Dame, Paris</atom:summary>
<media:group xmlns:media="http://search.yahoo.com/mrss/">
<media:keywords>church, paris</media:keywords>
</media:group>
</atom:entry>
--=_00fb9c5957c74e05312cbc2f9d1d09b8
Content-Type: image/jpeg
[binary data]
|
如果使用 Zend 库,那么事情会更简单。只需调用此 insertPhotoEntry() 方法,它会创建
清单 6 中的 POST 包并将其 Post 到此相册提要。清单 7 所示代码会构建一个 Web 表单,要求用户提供相册文件、标题和标记,然后再使用这个 Zend 库构造相应的 POST 包并将数据保存到相册:
清单 7:添加新照片
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Adding photos to an album</title>
<style>
body {
font-family: Verdana;
}
li {
border-bottom: solid black 1px;
margin: 10px;
padding: 2px;
width: auto;
padding-bottom: 20px;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
</style>
</head>
<body>
<h1>Add Photo</h1>
<?php if (!isset($_POST['submit'])) { ?>
<form method="post" action="<?php
echo htmlentities($_SERVER['PHP_SELF']); ?>" enctype="multipart/form-data">
Title: <br/>
<input name="title" type="text" size="25" /><p/>
File to upload: <br/>
<input name="photofile" type="file" /><p/>
Tags: <br/>
<input name="tags" type="text" size="25" /><p/>
<input name="submit" type="submit" value="Save" />
</form>
<?php
} else {
// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');
// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);
// validate input
if (empty($_POST['title'])) {
die('ERROR: Missing title');
}
// sanitize input
$title = htmlentities($_POST['title']);
$tags = htmlentities($_POST['tags']);
// set album name
$albumName = "France2008";
// construct photo object
// save to server
try {
$photo = $gphoto->newPhotoEntry();
// set file
$file = $gphoto->newMediaFileSource($_FILES['photofile']['tmp_name']);
$file->setContentType("image/jpeg");
$photo->setMediaSource($file);
// set title
$photo->setSummary($gphoto->newSummary($title));
// set tags
$photo->mediaGroup = new Zend_Gdata_Media_Extension_MediaGroup();
$keywords = new Zend_Gdata_Media_Extension_MediaKeywords();
$keywords->setText($tags);
$photo->mediaGroup->keywords = $keywords;
// link to album
$album = $gphoto->newAlbumQuery();
$album->setUser($user);
$album->setAlbumName($albumName);
// save photo
$gphoto->insertPhotoEntry($photo, $album->getQueryUrl());
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getResponse();
}
echo 'Photo successfully added!';
}
?>
</body>
</html>
|
清单 7 实际上包含两个部分:
- 一个 Web 表单
- PHP 代码,用来处理通过表单提交的输入
图 5 展示了这个表单的外观:
图 5. 可用来添加新照片的 Web 表单
一旦用户选择了要上传的文件,将标题和可选标记输入此表单并提交后,脚本的另一半就会发挥作用。首先,初始化一个 HTTP 客户机并打开通向 Picasa Web Albums Data API 的一个验证过的连接。接下来,验证此 Web 表单的输入,初始化一个新的 PhotoEntry() 对象来保存此新照片的数据。
输入到此表单的关键字和标题之后分别通过 mediaGroup 属性和 setSummary() 方法被附加到此对象。这个 PHP 形式的特别的文件上传数组 $_FILES 包含所上传文件的名称,setMediaSource() 方法可将这个文件附加到此对象。最后,setAlbumName() 方法指定照片所链接到的那个相册(将相册值设置为默认以便将图像放置到默认相册内或网络硬盘 内)。
配置了这些对象参数之后,insertPhotoEntry() 方法就会将照片和元数据保存到 Google 服务器。照片添加后,应该立即就能在相应的相册内看到它。
图 6 展示了成功添加照片后的输出:
图 6. 添加新照片后的结果
删除和修改照片
要删除一个照片,可以向照片的惟一 URL 发送一个 DELETE 请求。在这个 Zend 库的上下文,先使用照片和相册的 ID 构造这个照片的 URL,使用 getPhotoEntry() 方法获得对此照片(作为一个对象)的引用,然后再调用该对象的 delete() 方法。清单 8 展示了此过程:
清单 8:删除照片
<?php
// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');
// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);
// get photo entry
// delete entry
try {
$photo = $gphoto->getPhotoEntry( 'http://picasaweb.google.com/data/entry/api/
user/xxxxx/albumid/yyyyy/photoid/zzzzz');
$photo->delete();
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getResponse();
}
echo 'Photo successfully deleted!';
?>
|
要编辑照片,可以再次使用 getPhotoEntry() 方法。这次,为各种对象属性设置新值,然后调用此对象的 save() 方法以将更改保存回服务器。清单 9 展示了此过程:
清单 9:更新照片
<?php
// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');
// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);
// get photo entry
// delete entry
try {
$photo = $gphoto->getPhotoEntry('http://picasaweb.google.com/
data/entry/api/user/xxxxx/albumid/yyyyy/photoid/zzzzz');
// set new title
$photo->setSummary($gphoto->newSummary('New title'));
// set new tags
$photo->mediaGroup = new Zend_Gdata_Media_Extension_MediaGroup();
$keywords = new Zend_Gdata_Media_Extension_MediaKeywords();
$keywords->setText('new,tags');
$photo->mediaGroup->keywords = $keywords;
$photo->save();
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getResponse();
}
echo 'Photo successfully modified!';
?>
|

 |

|
过滤提要结果
Picasa Web Albums Data API 还能让您定制提要。您可以限制提要内的条目数量或只检索那些与搜索标准相匹配的条目。比如,如 清单 10 所示,如果向此提要 URL 添加 'max-results' 参数,就可以限制在提要响应内返回的条目数量:
清单 10:过滤提要结果
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Restricting feed results</title>
<style>
body {
font-family: Verdana;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
img {
float: left;
}
</style>
</head>
<body>
<?php
$userid = 'userid%40googlemail.com';
$album = 'France2008';
// build feed URL
$feedURL = "http://picasaweb.google.com/data/feed/api/
user/$userid/album/$album?max-results=3";
// read feed into SimpleXML object
$sxml = simplexml_load_file($feedURL);
// get album name and number of photos
$counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
$total = $counts->totalResults;
?>
<h1><?php echo $sxml->title; ?></h1>
<?php echo $total; ?> photo(s) found.
<p/>
<?php
// iterate over entries in album
// print each entry's title, size, dimensions, tags, and thumbnail image
foreach ($sxml->entry as $entry) {
$title = $entry->title;
$summary = $entry->summary;
$gphoto = $entry->children('http://schemas.google.com/photos/2007');
$size = $gphoto->size;
$height = $gphoto->height;
$width = $gphoto->width;
$media = $entry->children('http://search.yahoo.com/mrss/');
$thumbnail = $media->group->thumbnail[1];
$tags = $media->group->keywords;
echo "<h2>$summary</h2>\n";
echo "<table><tr><td><img src=\"" .
$thumbnail->attributes()->{'url'} . "\"/></td>\n";
echo "<td><span class=\"attr\">File</span>: $title
<br />\n";
echo "<span class=\"attr\">Size</span>: $size
($height x $width) <br />\n";
echo "<span class=\"attr\">Tags</span>: $tags
</td></tr></table>\n";
}
?>
</body>
</html>
|
此外,若使用 q 参数,还可以只检索那些与特定的查询字符串相匹配的条目。Picasa
将会搜索与查询字符串匹配的每个照片的标题、说明和标记。清单 11 所示的代码可以显示所有具有 ‘church’ 标记的照片:
清单 11:用关键字搜索照片
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Searching photos by tag</title>
<style>
body {
font-family: Verdana;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
img {
float: left;
}
</style>
</head>
<body>
<?php
$userid = 'userid%40googlemail.com';
$album = 'France2008';
// build feed URL
$feedURL = "http://picasaweb.google.com/data/feed/api/user/
$userid/album/$album?tag=church";
// read feed into SimpleXML object
$sxml = simplexml_load_file($feedURL);
// get album name and number of photos
$counts = $sxml->children('http://a9.com/-/spec/opensearchrss/1.0/');
$total = $counts->totalResults;
?>
<h1><?php echo $sxml->title; ?></h1>
<?php echo $total; ?> photo(s) found.
<p/>
<?php
// iterate over entries in album
// print each entry's title, size, dimensions, tags and thumbnail image
foreach ($sxml->entry as $entry) {
$title = $entry->title;
$summary = $entry->summary;
$gphoto = $entry->children('http://schemas.google.com/photos/2007');
$size = $gphoto->size;
$height = $gphoto->height;
$width = $gphoto->width;
$media = $entry->children('http://search.yahoo.com/mrss/');
$thumbnail = $media->group->thumbnail[1];
$tags = $media->group->keywords;
echo "<h2>$summary</h2>\n";
echo "<table><tr><td><img src=\"" .
$thumbnail->attributes()->{'url'} . "\"/></td>\n";
echo "<td><span class=\"attr\">File</span>: $title
<br />\n";
echo "<span class=\"attr\">Size</span>: $size
($height x $width) <br />\n";
echo "<span class=\"attr\">Tags</span>: $tags
</td></tr></table>\n";
}
?>
</body>
</html>
|
图 7 展示了可能的输出:
图 7. 按关键字搜索照片
集成 Picasa 动作
现在,您就可以将所有这些信息进行实际应用了。您接下来将构建一个简单的基于 PHP 的应用程序,充分利用 Picasa
Web Albums Data API 所提供的各种特性来查看、删除、添加和搜索给定相册内的照片。此原型应用程序具有 3 个脚本(参见 下载 小节):
- ‘list.php’ — 列出相册内的照片,并提供用以搜索、添加和删除照片的链接
- ‘add.php’ — 显示一个表单来添加一个新照片并处理此提交
- ‘delete.php’ — 删除一个特定照片
先以 ‘list.php’(清单 12)开始,它更新了 清单 4 以便每个照片现在都伴随有一个删除链接。此页还包含额外的一个搜索表单:
清单 12:列出照片
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Listing album contents</title>
<style>
body {
font-family: Verdana;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
img {
float: left;
}
</style>
</head>
<body>
<?php
// load library
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');
// create authenticated HTTP client for Picasa service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);
// generate query to get album feed
$query = $gphoto->newAlbumQuery();
$query->setUser("default");
$query->setAlbumName("France2008");
// filter by search term
if(isset($_GET['q'])) {
$query->setQuery($_GET['q']);
}
// get and parse album feed
// get album name and number of photos
try {
$feed = $gphoto->getAlbumFeed($query);
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getResponse();
}
?>
<h1><?php echo $feed->getTitle(); ?></h1>
<?php echo $feed->getTotalResults(); ?> photo(s) found.
<p/>
<?php
// process each photo entry
// print each entry's title, size, dimensions, tags, and thumbnail image
foreach ($feed as $entry) {
$title = $entry->getTitle();
$summary = $entry->getSummary();
$thumbnail = $entry->getMediaGroup()->getThumbnail();
$tags = $entry->getMediaGroup()->getKeywords();
$size = $entry->getGphotoSize();
$height = $entry->getGphotoHeight();
$width = $entry->getGphotoWidth();
$photoid = $entry->getGphotoId();
$albumid = $entry->getGphotoAlbumId();
echo "<h2>$summary</h2>\n";
echo "<table><tr><td><img src=\"" .
$thumbnail[1]->url . "\"/></td>\n";
echo "<td><span class=\"attr\">File</span>: $title
<br />\n";
echo "<span class=\"attr\">Size</span>: $size bytes
($height x $width) <br />\n";
echo "<span class=\"attr\">Tags</span>: $tags
<br />\n";
echo "<a href=\"delete.php?aid=$albumid&pid=$photoid\">
delete photo</a></td></tr></table>\n";
}
?>
<a href="add.php">Add a new photo</a>
<p/>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="get">
Search for photos containing:<br/>
<input type="text" name="q" size="10"/><p/>
<input type="submit" name="submit" value="Search"/>
</form>
</body>
</html>
|
图 8 展示了此脚本运行后的结果:
图 8. 列出相册内照片的 Web 页面
注意 清单 12 中的搜索表单一旦提交就会重新调用 list.php,并通过此查询对象的 setQuery() 方法 将用户的查询字符串附加到所请求的提要。
add.php 脚本添加新照片,如 清单 13 所示:
清单 13:添加照片
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Adding photos to an album</title>
<style>
body {
font-family: Verdana;
}
li {
border-bottom: solid black 1px;
margin: 10px;
padding: 2px;
width: auto;
padding-bottom: 20px;
}
h2 {
color: red;
text-decoration: none;
}
span.attr {
font-weight: bolder;
}
</style>
</head>
<body>
<h1>Add Photo</h1>
<?php if (!isset($_POST['submit'])) { ?>
<form method="post" action="<?php
echo htmlentities($_SERVER['PHP_SELF']); ?>" enctype="multipart/form-data">
Title: <br/>
<input name="title" type="text" size="25" /><p/>
File to upload: <br/>
<input name="photofile" type="file" /><p/>
Tags: <br/>
<input name="tags" type="text" size="25" /><p/>
<input name="submit" type="submit" value="Save" />
</form>
<?php
} else {
// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');
// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);
// validate input
if (empty($_POST['title'])) {
die('ERROR: Missing title');
}
// sanitize input
$title = htmlentities($_POST['title']);
$tags = htmlentities($_POST['tags']);
// set album name
$albumName = "France2008";
// construct photo object
// save to server
try {
$photo = $gphoto->newPhotoEntry();
// set file
$file = $gphoto->newMediaFileSource($_FILES['photofile']['tmp_name']);
$file->setContentType("image/jpeg");
$photo->setMediaSource($file);
// set title
$photo->setSummary($gphoto->newSummary($title));
// set tags
$photo->mediaGroup = new Zend_Gdata_Media_Extension_MediaGroup();
$keywords = new Zend_Gdata_Media_Extension_MediaKeywords();
$keywords->setText($tags);
$photo->mediaGroup->keywords = $keywords;
// link to album
$album = $gphoto->newAlbumQuery();
$album->setUser($user);
$album->setAlbumName($albumName);
// save photo
$gphoto->insertPhotoEntry($photo, $album->getQueryUrl());
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getResponse();
}
echo 'Photo successfully added!';
}
?>
</body>
</html>
|
图 9 展示了这个表单:
图 9. 用于添加新照片的 Web 表单
删除照片的 delete.php 脚本会通过 GET 方法从 list.php 接受惟一的照片 ID 和相册 ID。delete.php 脚本使用此信息来定位和删除照片项。清单 14 给出了代码:
清单 14:删除照片
<?php
// check for album and photo ID
if (empty($_GET['aid']) || empty($_GET['pid'])) {
die('ERROR: Missing input parameters');
} else{
$aid = htmlentities($_GET['aid']);
$pid = htmlentities($_GET['pid']);
}
// load classes
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Photos');
Zend_Loader::loadClass('Zend_Http_Client');
// connect to service
$svc = Zend_Gdata_Photos::AUTH_SERVICE_NAME;
$user = "userid@gmail.com";
$pass = "secret";
$client = Zend_Gdata_ClientLogin::getHttpClient($user, $pass, $svc);
$gphoto = new Zend_Gdata_Photos($client);
// get photo entry
// delete entry
try {
$photo = $gphoto->getPhotoEntry('http://picasaweb.google.com/data/
entry/api/user/userid/albumid/' . $aid . '/photoid/' . $pid);
$photo->delete();
} catch (Zend_Gdata_App_Exception $e) {
echo "Error: " . $e->getResponse();
}
echo 'Photo successfully deleted!';
?>
|
结束语
在本文中您亲历了一个快捷教程,了解了如何使用 SimpleXML 和 Zend 客户库将来自 Picasa Web Albums 服务的数据集成到一个 PHP 应用程序。本文中的示例向您简介了 Picasa 提要格式并向您展示了如何完成以下操作:
- 检索相册和照片列表
- 通过搜索条件过滤这些列表
- 添加、修改和删除照片
- 构建一个面向 Picasa 服务的定制接口
正如这些示例所展示的,Picasa Web Albums Data API 是一种功能强大且灵活的工具,可被开发人员用来围绕照片管理和存储构建创新型应用程序。您不妨尝试使用,亲自体验一下!
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| 本文的示例代码 | x-picasalbum-example.zip | 4KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
关于作者  | |  | Vikram Vaswani 是 Melonfire 的创始人和 CEO,该公司是一家专门研究开源工具和技术的咨询服务公司。他还著有 PHP Programming Solutions 和 How to do Everything with PHP and MySQL 等著作。 |
对本文的评价
|