领先一步
VMware 提供培训和认证,助您加速进步。
了解更多在上一篇文章中,我描述了我们如何使用自定义 ANT 任务从 Spring 产品组合中基于 ANT 的项目上传每日快照。在这篇文章中,我将描述我们如何使用 Amazon S3 为每个项目的快照生成页面并允许用户下载快照。
正如我在上一篇文章中提到的,S3 主要用作 RESTful 服务。这意味着,虽然我在上传部分使用了 Java,但在下载部分,我可以自由使用其他语言。在这种情况下,我选择了 PHP,因为它已经存在于我正在使用的服务器上,并且是阻力最小的路径。
这项工作有两个部分。第一部分是我需要查询 Amazon S3 服务,以获取给定 Spring 项目的快照列表。要做到这一点,您需要创建一个带有前缀参数的 REST 查询。
http://s3.amazonaws.com/static.springframework.org/?prefix=$prefix
既然您已经了解了基本的查询方法,我想回到之前的示例,并指出上传定义中的一些重要部分。
<aws:s3 accessKey="${s3.accessKey}" secretKey="${s3.secretKey}">
<upload bucketName="static.springframework.org"
file="${target.release.dir}/${release-with-dependencies.zip}"
toFile="SPR/spring-framework-${spring-version}-with-dependencies-${tstamp}-${build.number}.zip"
publicRead="true"/>
<upload bucketName="static.springframework.org"
file="${target.release.dir}/${release.zip}"
toFile="SPR/spring-framework-${spring-version}-${tstamp}-${build.number}.zip"
publicRead="true"/>
</aws:s3>
您注意到的第一件事是,对于 Spring 工件,我选择了用 SPR 作为前缀。文件名本质上是自由形式的,所以使用斜杠,您可以创建虚拟目录结构进行查询。如果您查看 Spring Web Flow 的构建,您会发现它的工件前缀是 SWF,Spring LDAP 的工件是 LDAP,而 Spring Modules 的工件是 MOD。因此,通过自定义我们的查询参数,我们可以专门选择一个项目。
http://s3.amazonaws.com/static.springframework.org/?prefix=SPR
http://s3.amazonaws.com/static.springframework.org/?prefix=SWF
http://s3.amazonaws.com/static.springframework.org/?prefix=LDAP
http://s3.amazonaws.com/static.springframework.org/?prefix=MOD
第二件需要注意的事情是 publicRead=true 声明。默认情况下,S3 不允许任何人访问或下载您的存储桶。您可以通过使用您的密钥和访问密钥创建一个允许下载的令牌来给予他们权限。然而,在这项工作中,我认为这是不必要的。快照是公开可访问的,所以我放宽了安全设置,允许它们无需令牌即可下载。
现在您可以调用 S3 REST 服务并获得存储桶中项目的正确过滤列表,但响应是原始 XML。即使我是一名 Spring 开发者,在浏览器中查看原始 XML 也不会让我兴奋。;) 所以流程的下一步是将 XML 转换为有用的 HTML 页面。这时我有两个选择。我可以选择在服务器上执行转换以生成 HTML,然后将其返回给用户,或者我可以将 XML 和 XSLT 文件一起返回给用户,然后让用户的浏览器为我执行转换。现在我必须诚实地说,后者可以减轻服务器的负担,并且实际上允许用户的浏览器缓存转换以提高性能。但现实是,我就是无法访问 XSLT PHP 库,所以即使我想,我也无法进行服务器端转换。我意识到一些旧的浏览器会在这方面遇到问题,但到时候我们再处理。
所以,我需要获取返回的 XML
<ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<Name>static.springframework.org</Name>
<Prefix>SPR</Prefix>
<Marker/>
<MaxKeys>1000</MaxKeys>
<IsTruncated>false</IsTruncated>
<Contents>
<Key>SPR/spring-framework-2.0.5-20070411-50.zip</Key>
<LastModified>2007-04-11T13:27:34.000Z</LastModified>
<ETag>"1ab20ad18ca0edb4a360279f27409d54"</ETag>
<Size>10725241</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
<Contents>
<Key>SPR/spring-framework-2.0.5-20070411-51.zip</Key>
<LastModified>2007-04-12T01:25:58.000Z</LastModified>
<ETag>"de2e5833ae8fe4cc06987935bea06e57"</ETag>
<Size>10727049</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
<Contents>
<Key>SPR/spring-framework-2.0.5-20070412-52.zip</Key>
<LastModified>2007-04-13T01:22:23.000Z</LastModified>
<ETag>"414b947226fc4e08bd118e0f16a6be67"</ETag>
<Size>10736732</Size>
<StorageClass>STANDARD</StorageClass>
</Contents>
...
并将其转换为 HTML
服务返回的大部分内容对这项工作没有用处,因此 XSLT 变得非常简单。
<xsl:template match="/">
<head>
<style type="text/css" media="all">@import "./snapshot-download.css";</style>
</head>
<body>
<xsl:apply-templates select="s3:ListBucketResult"/>
</body>
</xsl:template>
<xsl:template match="s3:ListBucketResult">
<xsl:variable name="bucket-name" select="s3:Name"/>
<table>
<tr>
<th class="name"><xsl:value-of select="s3:Prefix"/> Project Snapshots</th>
<th class="size">Size</th>
</tr>
<xsl:for-each select="s3:Contents">
<tr>
<td class="name">
<a class="name" href="http://s3.amazonaws.com/{$bucket-name}/{s3:Key}">
<xsl:value-of select="substring-after(s3:Key, '/')"/>
</a>
</td>
<td class="size"><xsl:value-of select="format-number(s3:Size div 1048576, '###,###.0')"/> MB</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
转换从一些 HTML 声明开始,然后遍历存储桶的每个项目。然后它使用对象标识符在 S3 服务器上创建指向该文件的链接。就是这样。PHP 页面为 XML 调用 S3,然后将其连同 XSLT 声明一起传递给用户的浏览器。
<?php
$prefix = $HTTP_GET_VARS["project"];
$url = "http://s3.amazonaws.com/static.springframework.org/?prefix=$prefix";
$xml = file_get_contents($url);
header('Content-Type: text/xml; charset=UTF-8');
echo '<?xml version="1.0" encoding="UTF-8"?>';
echo '<?xml-stylesheet type="text/xsl" href="./snapshot-download.xsl"?>';
echo substr($xml, 39);
?>
通过请求参数为每个项目添加一些自定义,您就可以为每个项目获得单独的下载页面。
我的 Amazon S3 服务探索到此结束。根据我的经验,我可以肯定地说,如果您有大量数据和大量的带宽需求,很少有地方能给您更好的价格。而且由于其 RESTful 接口,它足够灵活,可以与您喜欢的任何语言一起使用。感谢您的聆听,我现在可以回答任何问题。:)