您的位置:首页 > 编程语言 > PHP开发

使用Frontpage RPC管理web站点的文件

2005-11-29 21:43 302 查看
 往往我们需要对一个web站点的文件进行管理,而常用两种方式:第一,通过ftp协议进行文件管理;第二,通过web页面提供的该功能(yahoo的公文包)。而这里将介绍第三种方式:FrontPage 服务器扩展(FrontPage Server Extensions Remote Procedure Call)。使用FrontPage 服务器扩展有以下优点:l          使创作者们能协作创建和维护web站点、直接在服务器计算机上编辑一个 Web 站点(节省下载时间),并且在不必编写程序的情况下,轻易地在站点上加入新功能。 l          支持站点计数器、全文搜索、电子邮件表单处理程序和其他由创作者使用 FrontPage 添加到站点的功能。您不必下载、购买或安装独立的CGI兼容的程序来实现上述功能。 l          能在许多流行的服务器平台,如 Windows NT 和 UNIX,以及许多流行的站点服务器,如 Microsoft Internet Information Services (IIS)、Apache、WebSite 和 Netscape 上工作。 l          在一个 Web 站点中移动、删除或重命名一个网页(只是网页的文件名,而不是必须传送到站点服务器的整个文件的名称)后,自动更新超链接。 l          支持与 Microsoft Office、Visual SourceSafe 和 Index Server 的集成。Frontpage RPC通过Frontpage RPC 方法来控制web站点,实现以上的功能。这里只是介绍如何通过Frontpage RPC对web站点的文件进行管理。对大家起一个抛砖引玉的作用。Frontpage RPC的是基于http协议的一种远程过程调用。Frontpage RPC通过http POST命令向web站点中特定的dll发送方法,而web服务器将返回带有操作结果信息HTML文档到客户端。客户端可通过该文档判断是否操作成功。Frontpage RPC方法位于“method=”后,方法名后面有一个冒号“:”,它是方法名与Frontpage 服务器扩展的版本号的分隔符。版本号后面跟着该方法的参数。每个参数以记号“&”作为第一个字母,参数名紧跟“&”后面。参数名与参数的值用“=”连接,中间不能由任何的空格符号。可以参见下面的例子:method=get document:server_extension_version
&service_name=/&document_name=service_relative_path/file_name
[&dir_name=directory_name][&effective_protocol_version=server_extension_version]
&old_theme_html=(true|false)&force=(true|false)[&doc_version=string]
&get_option=(none|0|1|2)&timeout=time_in_seconds[&validateWelcomeNames=(true|false)]
 
字体/代码意义例子
斜体变量(参数)的值service_relative_path/file_name
方括号([、])可选的内容[&validateWelcomeNames=(true|false)]
无格式文本字面意义method
分隔符(|)分开可选的选项(true|false)
接下来看看在这里将会使用到的Frontpage RPC 方法,具体的参数可以参看(http://msdn.microsoft.com/library/en-us/spptsdk/html/SPPTWSSFPSERPC_SV01072918.asp?frame=true):l          get document 获取指定的文档。l          list documents 列出位于指定url的web站点下文件、文件夹和子站点以及他们的meta-info。l          move document修改指定文件的文件名、移动指定的文件到指定的文件夹、复制指定文件。l          put document 上传一个文件或文件夹到已存在的web站点。l          remove documents 删除wen站点上指定的文件或文件夹。在编码的过程中应该注意一下几点:1.          url编码问题:l          在http协议中发送的数据主体必须是8位编码的字符,也就是只能由0-225之间的字符组成。中文字符是不能出现的。所以在所有Frontpage RPC中方法中所有的参数都需要经过url编码。url编码方式是把字符相对应的二进制的值转换为十进制,然后再前面加“%”。url中文的编码方式先将中文编码成对应的字节,然后在在前面加上“%”。比如“中国”使用UTF-8的编码是“228”,“184”,“173”,“229”,“155”,“189”六个字节组成,那么url的对应得编码应该是“%228%184%173%229%155%189”。如果“中国”使用gb2312的编码是“214”,“208”,“185”,“250”四个字节,那么对应的url编码应该是“%214%208%185%250”l          Frontpage RPC 中方法中所有的参数不能出现除数字和字母以外的字符,例如一般可以在地址栏看到的符号“.”、“_”都不允许出现在参数中。C#提供的UrlEncode方法不会对“.”、“_”这两个字符进行编码,所以我们需要写一个函数进行编码。l          文件的url中如果带有“;”、“=”、“[”、“]”都需要转义为“/;”、“/=”、“/[”、“/]”才进行url编码。否则会提示找不到该文件。2.          html编码问题:html的编码与url相类似,只是html编码会将UTF-8“中国”编码为:“ä&# 184;&# 229;&# 155;&# 155;&# 189;”,gb2312编码为“Ö&# 208;&# 185;&# 250;”。3.          注意方法中的大小写。这个问题我是在写这篇文章的时候,做演示工程的时候发现的问题。因为实际使用中可能是版本的问题,大小写与sdk中的有些出入。例如oldUrl正确的是参数名应该是oldUrl,而微软官方文档中的是oldURL。4.          Web站点和子站点的关系。曾经在开发的过程中,忽略的这个问题最后的直接后果是导致加班到晚上1点。在操作不同的子站点的时候,Frontpage RPC 方法发送的dll的url也是不一样的。而且子站点与子站点是独立的。不能够进行类似将子站点A的文件复制到子站点B这样的操作。最后还是看看一些关键的代码: 
using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Threading;
using System.Net.Sockets;
 
namespace FPSERPCClient
{
   /// <summary>
   /// Summary description for FPSEPublish.
   /// </summary>
   public class FPSERPCClient
   {
     /// <summary>
     /// 构造函数
     /// </summary>
     /// <param name="username">用于登陆站点的用户名</param>
     /// <param name="password">用于登陆站点的密码</param>
     public FPSERPCClient(string username, string password)
     {
        Credential = new NetworkCredential(username, password);
     }
     /// <summary>
     /// 删除web站点上指定的文件或文件夹。
     /// </summary>
     /// <param name="uri">删除文件的url</param>
     /// <returns></returns>
     public string RemoveDocument(string uri)
     {
        Uri myUri = new Uri(uri, true);
        string webUrl, fileUrl;
        UrlToWebUrl(uri, out webUrl, out fileUrl);
        /// 这是最简单的一个方法
        string postBody = String.Format("
        method=remove documents&service_name={0}&url_list=[{1}]",
          UrlEncode(webUrl),
          UrlEncode(fileUrl));
        return SendRequest(myUri.GetLeftPart(UriPartial.Authority) +
          webUrl.TrimEnd('/') + "/_vti_bin/_vti_aut/author.dll", postBody);
     }
 
     /// <summary>
     /// 发送Frontpage RPC方法的请求重载
     /// </summary>
     /// <param name="uri">发送请求的目标Url</param>
     /// <param name="postBody">发送请求的主体</param>
     /// <returns></returns>
     private string SendRequest(string uri, string postBody)
     {
        return SendRequest(uri, postBody, null);
     }
 
     /// <summary>
     /// 发送Frontpage RPC方法的请求重载
     /// </summary>
     /// <param name="uri">发送请求的目标Url</param>
     /// <param name="postBody">发送请求的主体</param>
     /// <param name="fileStream">下载文件保存的FileStream</param>
     /// <returns></returns>
     private string SendRequest(string uri, string postBody, Stream fileStream)
     {
        byte[] bPostBody = BodyEncoding.GetBytes(postBody);
        return SendRequest(uri, bPostBody, bPostBody.Length, fileStream);
     }
 
  
     /// <summary>
     ///  发送Frontpage RPC方法的请求重载
     /// </summary>
     /// <param name="uri">发送请求的目标Url</param>
     /// <param name="postBody">发送请求的主体</param>
     /// <param name="postLength">发送请求的主体长度</param>
     /// <param name="fileStream">下载文件保存的FileStream</param>
     /// <returns>返回接受的Response,为html格式的字符串</returns>
     private string SendRequest(string uri, byte[] postBody, long postLength, Stream fileStream)
     {
        string strResponseText = null;
        Stream sendStream = null;
        HttpWebResponse response = null;
        Stream receiveStream = null;
        StreamReader responseTestReader = null;
        try
        {
          HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
          request.Method = "POST";
          request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";
          request.Headers.Add("X-Vermeer-Content-Type", "application/x-www-form-urlencoded");
          request.UserAgent = "DRSERPCClient";
          request.Accept = "auth/sicily";
          request.Expect = "200-ok";
          request.KeepAlive = true;
          request.Credentials = this.Credential;
          request.Timeout = HTTPREQUEST_TIMEOUT;
          request.PreAuthenticate=true; // let's stop sending bunks of data prior to detecting 401
         
          sendStream = request.GetRequestStream();
 
          int iOffset = 0;
          while(postLength > 0)
          {
            if (postLength > 4096)
            {
               sendStream.Write(postBody, iOffset, 4096);
               postLength -= 4096;
               iOffset += 4096;
            }
            else
            {
               sendStream.Write(postBody, iOffset, Convert.ToInt32(postLength));
               break;
            }
          }
 
          sendStream.Close();
 
          response = (HttpWebResponse)request.GetResponse();
          receiveStream = response.GetResponseStream();
         
          int readBytes = 0;
          byte[] readBuffer = new byte[BUFFER_SIZE];
         
          ///接受到的Response以“</HTML>/n”为分割符,后面的为下载文件的主体部分
          while((readBytes = receiveStream.Read(readBuffer,0, readBuffer.Length)) != 0)
          {
            strResponseText += BodyEncoding.GetString(readBuffer, 0, readBytes);
            int separatorOffset = strResponseText.ToUpper().IndexOf("</HTML>") + 8;
            if(separatorOffset != 7)
            {
              
               strResponseText = strResponseText.Substring(0, separatorOffset);
               if(fileStream != null)
               {
                 fileStream.Write(readBuffer, separatorOffset % BUFFER_SIZE , readBytes - separatorOffset);
               }
               break;
            }
          }
          ///把下载文件的内容写入文件流中,最后保存在磁盘上
          if(fileStream != null)
          {
            while((readBytes = receiveStream.Read(readBuffer,0, readBuffer.Length)) != 0)
            {
               fileStream.Write(readBuffer, 0, readBytes);
            }
          }
 
          receiveStream.Close();
          response.Close();
         
        }
        catch (Exception e)
        {
          if(sendStream != null)
            sendStream.Close();
          if(responseTestReader != null)
            responseTestReader.Close();
          if(receiveStream != null)
            receiveStream.Close();
          if(response != null)
            response.Close();
          throw e;
        }
 
        return strResponseText;
     }
 
     /// <summary>
     /// 获取一个绝对Url的字站点地址,和相对该子站点的文件地址
     /// </summary>
     /// <param name="uri">绝对URL</param>
     /// <param name="webUrl">子站点地址</param>
     /// <param name="fileUrl">相对子站点的文件地址</param>
     private void UrlToWebUrl(string uri, out string webUrl, out string fileUrl)
     {
        Uri myUri = new Uri(uri, true);
        string strUriPartial = string.Empty;
        for(int i = 0;i < myUri.Segments.Length; i++ )
          strUriPartial += myUri.Segments[i];
 
        string postBody = String.Format("method=url+to+web+url&url={0}&flags=0", UrlEncode(strUriPartial));  
        string response = SendRequest(myUri.GetLeftPart(UriPartial.Authority) + "/_vti_bin/shtml.dll/_vti_rpc",postBody);
        webUrl = GetReturnValue(response, "webUrl");
        fileUrl = GetReturnValue(response, "fileUrl");
     }
 
      /// <summary>
     /// 获取一个返回的html中特定的值
     /// </summary>
     /// <param name="responseText">web站点返回的html字符串</param>
     /// <param name="key">需要获取值得key</param>
     /// <returns>返回该key的值 </returns>
     public string GetReturnValue(string responseText, string key)
     {
        int start = responseText.IndexOf(key + "=");
        if (-1 == start)
          return null;
        else
          start += key.Length + 1;
 
        int end = responseText.IndexOf("/n", start);
        return HtmlDecode(responseText.Substring(start, end - start));
     }
 
     /// <summary>
     /// 获取一组返回的html中特定的值
     /// </summary>
     /// <param name="responseText">web站点返回的html字符串</param>
     /// <param name="key">需要获取值得key</param>
     /// <returns>返回该key的值</returns>
     public string[] GetReturnValues(string responseText, string key)
     {
        int start = 0;
        int end = 0;
        string returnValue = string.Empty;
        ArrayList returnValuesList = new ArrayList();
        while(true)
        {
          start = responseText.IndexOf(key + "=", end) + key.Length + 1;
          if(start == key.Length)
            break;
          end = responseText.IndexOf("/n", start);
          returnValue = responseText.Substring(start, end - start);
          returnValuesList.Add(HtmlDecode(returnValue));
        }
        string[] returnValues = new string[returnValuesList.Count];
        returnValuesList.CopyTo(returnValues);
        return returnValues;
     }
     /// <summary>
     /// url编码
     /// </summary>
     /// <param name="url">需进行编码的URL</param>
     /// <param name="e">进行编码的类</param>
     /// <returns>返回编码以后的值</returns>
     public string UrlEncode(string url, Encoding e)
     {
        url = url.Replace(";", "//;");
        url = url.Replace("=", "//=");
        url = url.Replace("[", "//[");
        url = url.Replace("]", "//]");
        string encodedUrl = HttpUtility.UrlEncode(url, e);
        encodedUrl = encodedUrl.Replace(".", "%2e");
        encodedUrl = encodedUrl.Replace("_", "%5f");
        return encodedUrl;
     }
     /// <summary>
     /// url编码
     /// </summary>
     /// <param name="url">需进行编码的URL</param>
     /// <returns>返回编码以后的值</returns>
     public string UrlEncode(string url)
     {
        return this.UrlEncode(url, UrlEncoding);
     }
     /// <summary>
     /// html编码
     /// </summary>
     /// <param name="html">需进行编码的html</param>
     /// <param name="e">进行编码的类</param>
     /// <returns>返回编码以后的值</returns>
     public string HtmlDecode(string html, Encoding e)
     {
        string htmlDecoded = HttpUtility.HtmlDecode(html);
        byte[] htmlDecodedBytes = Encoding.Unicode.GetBytes(htmlDecoded);
 
        char[] htmlDecodedChars = Encoding.Unicode.GetChars(htmlDecodedBytes);
        htmlDecodedBytes = new byte[htmlDecodedChars.Length];
        for(int i = 0; i < htmlDecodedChars.Length; i++)
        {
          htmlDecodedBytes[i] = (byte)htmlDecodedChars[i];
        }
        htmlDecoded = e.GetString(htmlDecodedBytes);
        return htmlDecoded;
     }
     /// <summary>
     /// html编码
     /// </summary>
     /// <param name="html">需进行编码的html</param>
     /// <returns>返回编码以后的值</returns>
     public string HtmlDecode(string html)
     {
        return this.HtmlDecode(html, HtmlEncoding);
     }
   }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐