HomeLinks:它是什么以及如何实现
如何实现一个使用 XML、AJAX 和 Web Services 的机制,为您的 Web 共享本地文件提供链接。
引言
在线共享文件最简单的方法就是将它们上传到您的 Web 空间,然后为他人提供正确的链接。文档文件、电子表格、图片和 MP3 文件都很小,可以轻松上传。但是,如果您想共享一大堆文件,例如 MPG 视频文件呢?如果您不愿意将 100MB 的文件 FTP 到您的 Web 主机,那么您仍然有一个选择:自己托管它们,并提供指向您计算机上运行的 Web 服务器的链接。您只需要一个静态 IP 和安装并运行的 IIS(或任何其他 Web 服务器)。在这种情况下,还有一个最后的注意事项。无论您的家用电脑能在线多久,它最终都会关机,这将导致链接失效。无论您关闭电脑 5 分钟还是 5 小时,断开的链接始终是一个麻烦。这时 HomeLinks 就派上用场了,它是一种防止断开链接和惹恼 Web 用户的方法!此外,HomeLinks 是异步、客户端 JavaScript 调用 XML Web Services 的一个展示!
背景
在深入研究代码之前,有一些设置要求需要满足。
- 您必须在您的计算机上运行一个 Web 服务器。homelinks.xml 文件以及您想在线共享的其他文件所在的本地文件夹必须通过您的 Web 服务器公开可用。您可以创建一个虚拟目录,或者将该文件夹放在 Web 服务器的根目录下。无论哪种情况,以下测试 URL 都必须可访问:
http://127.0.0.1/(VIRTUAL) DIRECTORY NAME
- 您的 Web 服务器必须能够从您的 LAN 外部访问。如果您的计算机位于路由器/防火墙后面,那么您必须进行配置,以允许访问端口 80 并将传入的 HTTP 调用转发到 Web 服务器。确保您也在(Windows)防火墙设置中打开了端口 80!
- 最好有一个静态 IP,虽然不是强制性的。您始终可以使用您的 ISP 动态分配的当前 IP 来运行此处演示的示例应用程序。或者,您可以将动态 IP 分配给一个自动更新的域名,这样人们就可以始终访问您的 Web 服务器。这可以通过 DynDNS 等免费服务来完成,这些服务允许您选择您喜欢的域名,将其与您的动态 IP 相关联,并在您的 ISP 更改您的 IP 时自动更新它。在我们的例子中,无论我的 IP 是什么,Web 服务器都监听以下动态分配的域名:
http://dpant.homeip.net
人们可以使用 URL 访问我们的示例“rally_mavro_rodo”虚拟目录:
http://dpant.homeip.net/rally_mavro_rodo
- 除了 homelinks.xml 文件之外,包含在源 Zip 文件中的所有其他源文件都必须放在您的远程 Web 主机上的一个 HomeLinks ASP.NET Web 应用程序下。如果您在本地安装了 IIS,当然可以在您的计算机上运行 Web 应用程序,但请确保在 homelinks.xml 文件中包含正确的 URL(例如,伪静态域名将无法工作;请使用您的本地 IP 代替)。由于 Web 应用程序促进了 Web 服务,请确保在 web.config 文件中包含以下行:
<system.web> ... <webServices> <protocols> <add name="HttpGet"/> <add name="HttpPost"/> </protocols> </webServices> </system.web>
使用代码
在图 1 中,您可以看到 HomeLinks 的架构。HomeLinks 由以下组件构成:
- 一个 XML Web 服务 (HomeLinksService.asmx)。
- homelinks.xml 文件。
- 服务使用者(源 Zip 文件中的 HomeLinks.htm 或 ShowHomeLinks.htm)。
homelinks.xml
此文件向 XML Web 服务提供将显示给最终用户的链接。换句话说,HLink
节点由 Web 服务转换为 HTML 超链接。homelinks.xml 文件位于您计算机的 Web 共享文件夹中,因此您可以通过添加或删除 HLink
节点来轻松决定哪些文件将在网上可用。
<?xml version="1.0" encoding="utf-8" ?>
<HomeLinks>
<HLink href="http://dpant.homeip.net/rally_mavro_rodo/MOV02573.MPG"
target="_blank">Blaxokerasia 1 (2,4Mb)</HLink>
<HLink href="http://dpant.homeip.net/rally_mavro_rodo/MOV02578.MPG"
target="_blank">Blaxokerasia 2 (1,6Mb)</HLink>
<HLink href="http://dpant.homeip.net/rally_mavro_rodo/MOV02579A.WMV"
target="_blank">Blaxokerasia 3 (1.9Mb)</HLink>
...
<HomeLinks>
XML Web 服务
为了使用 Web 服务,我们调用 HomeLinks
方法,该方法接受一个参数:homelinks.xml 文件所在的 URI。在我们的示例中,我们提供了 http://dpant.homeip.net/rally_mavro_rodo URL。Web 服务尝试访问 homelinks.xml 文件,使用 MSXML 解析器读取 HLink
节点,并创建并返回一个 HTML A 链接的 XML 格式文档。例如,上面的第一个 HLink
节点会生成此 HTML 链接:
<a href="http://dpant.homeip.net/rally_mavro_rodo/MOV02573.MPG"
target="_blank">Blaxokerasia 1 (2,4Mb)</a>
如果 homelinks.xml 文件不可访问(您的计算机已关机、离线,或您的 Web 服务器已停止),Web 服务将简单地返回一个错误消息(NO_HOMELINKS
),说明该情况。这样,我们就避免了向用户显示断开的链接。XML Web 服务是用 C# 编写的。HomeLinks
方法在服务器端通过导入 System.Xml
.NET 命名空间使用 MSXML。XmlDocument
对象的 Load
方法用于访问 XML 文档,documentElement
属性表示已加载到内存中的 XML 文件的根元素,而 SelectNodes
方法允许我们对 XML 数据应用 XPath 表达式。
public class HomeLinksService : System.Web.Services.WebService {
const string NO_HOMELINKS =
"The {0} URI is currently unreachable (probably offline)";
const string BR = "<br/>";
const string A = "<a href='{0}' target='{1}'>{2}</a>";
[WebMethod]
public string HomeLinks(string URI) {
XmlDocument hlDoc = new XmlDocument();
try
{
string links = String.Empty;
hlDoc.Load(FixURI(URI) + "homelinks.xml");
XmlNodeList hlinks = hlDoc.DocumentElement.SelectNodes("HLink");
for (int i = 0; i < hlinks.Count; i++)
{
links += String.Format(A, hlinks[i].Attributes["href"].Value,
><>hlinks[i].Attributes["target"].Value, hlinks[i].InnerText) + BR;
}
return links;
}
catch (Exception) {
return String.Format(NO_HOMELINKS, URI);
}
}
}
服务使用者
图 1 显示了两个可能的 Web 服务使用者。HomeLinks.htm(或源 Zip 文件中的 HomeLinks.htm)文件可以是 Web 应用程序的一部分(使用者 A),也可以位于 Internet 上的任何其他位置(使用者 B)。不幸的是,使用者 B 受 XmlHttpRequest
对象安全限制,只能与 Internet Explorer 6 一起工作。无论哪种方式,我们都通过 JavaScript 使用 XmlHttpRequest
对象访问 Web 服务。这是一个异步、客户端、GET HTTP 调用 Web 服务器资源。这可以是任何东西,从简单的文本或 HTML 文件到 ASPX/PHP/Java/CGI 脚本。当服务器返回结果时,会调用 onreadystatechange
回调函数。Web 服务始终以 XML 格式返回结果。请注意 XmlHttpRequest
对象的 readyState
和 status
属性。它们指示异步调用是否成功。最后但同样重要的是,请注意 XmlHttpRequest
对象实例的创建取决于浏览器。这是完整的脚本代码:
<script type="text/javascript">
var req = false;
function getHomeLinks() {
// Obtain the XMLHttpRequest object for ...
if (window.ActiveXObject)
// ... IE
req = new ActiveXObject("Msxml2.XMLHTTP");
else if (window.XMLHttpRequest)
// ... or Mozilla
req = new XMLHttpRequest();
if (req) {
// Call the XML Web Service and pass the URI location of the
// homelinks.xml file
req.open("GET", "HomeLinksService.asmx/HomeLinks?" +
"URI=http://dpant.homeip.net/rally_mavro_rodo", true);
req.onreadystatechange = function() {
// Callback inline function
if (req.readyState == 4) {
if (req.status == 200)
// Simply display the HTML hyperlinks inside the divHL DIV
document.getElementById("divHL").innerHTML =
req.responseXML.documentElement.firstChild.nodeValue;
else
// The AJAX response indicates
// error - display verbose error message
document.getElementById("divHL").innerHTML = "readyState = " +
req.readyState + ", status = " +
req.status + " (" + req.statusText + ")";
// either case, no more waiting
document.getElementById("divWait").style.visibility = "hidden";
}
else {
// display wait popup while request is in progress
document.getElementById("divWait").style.visibility = "visible";
}
}
// initiate the AJAX request
req.send(null);
}
else {
// XHR object not supported - abort
document.write("Unable to create the XMLHttpRequest object.");
}
}
</script>
这是 HomeLinks.htm(或源 Zip 文件中的 ShowHomeLinks.htm)中的调用:
<body onload="getHomeLinks(); return true;">
<div>
<div id="divHL"></div>
<div id="divWait"
style="left: 50%; top: 50%; margin-top: 222px;
margin-left: -113px; position: absolute; visibility: hidden;
vertical-align: middle; width: 226px;
color: #3366cc; height: 111px; background-color: #ffff99;
text-align: center; border-right: #3333cc 1px solid;
border-top: #3333cc 1px solid; border-left: #3333cc 1px solid;
border-bottom: #3333cc 1px solid; top: 0px;">
<br /><br /> HomeLinks loading, Please wait ...
</div>
</div>
</body>
示例应用程序结果
在我们的示例中,超链接指向一系列 MPG 视频文件(带有有趣的希腊语名称),这些文件取自一个拉力赛活动。您可以在我的博客文章中查看它们。当然,HomeLinks 只有在我的电脑运行并且在线时才能使用;)
这是我们示例应用程序的两个屏幕截图:
关注点
如何调试
调试此项目肯定需要您花费不少时间。Web 服务和 XmlHttpRequest
对象可能会非常令人头疼,尤其是由于所有令人沮丧的错误消息和没有调试工具。此外,安全和配置问题也会阻碍您的成功之路。在此,我列出您将遇到的最常见的陷阱:
XmlHttpRequest 返回内部服务器错误(状态 = 500)
- 确保您已将以下配置行添加到 ASP.NET Web 应用程序的 web.config 文件中:
<system.web> <webServices> <protocols> <add name="HttpGet"/> <add name="HttpPost"/> </protocols> </webServices> </system.web>
- 确保您使用 GET HTTP 方法调用 Web 服务并传递正确的参数。
- 确保您将
readyState
、status
和statusText
的值显示在一个DIV
或TEXTAREA
对象中。请勿为此目的使用document.write()
。
XmlHttpRequest 返回未找到(状态 = 404)
- 确保您使用正确的 URL 指向 .asmx 文件。
- Web 服务方法调用区分大小写。在我们的示例中,请输入 HomeLinks,而不是 homeLinks 或 homelinks。
JavaScript 错误:未捕获的异常:拒绝访问方法 XmlHttpRequest.open
- 确保将使用者文件放在与 Web 服务相同的域下。这是浏览器强制执行的安全限制。Internet Explorer 会发出警告,但最终会执行调用,而 Mozilla Firefox 则不会。
JavaScript 返回空
- 确保您将
readyState
、status
和statusText
的值显示出来。请不要为此目的使用document.write
,因为这是一个异步调用,最新的结果会覆盖之前的结果。请使用DIV
或TEXTAREA
对象。 - 确保您将 XML 响应显示在
DIV
或TEXTAREA
对象中。请不要为此目的使用document.write
。 - 确保您正确处理 XML 文档。
- 使用 Firefox 错误控制台检查编码错误。