2010/07/28

[ASP.NET] 在 html 中加入遠端網頁的內容

  1. 使用 <iframe>: 這種方式大概是最常被使用到的.
    Sample:
    <iframe NAME="outer_frame" width="100%" height="100%" 
      frameborder="0" src="http://www.w3schools.com/" ></iframe>
    Note: iframe 的 width 或 height 設定成 100% 時, 並不會依 iframe 網頁內容而造成無捲軸的現象. 若要透過 javascript 去依 iframe 的內容調整 iframe 的 width 或 height, 也只有同 iframe 所嵌頁面與外部網頁同 domain 的情況下可行, 不同 domain 會因 access deny (存取被拒) 而無法完成此修改 width 或 height 的動作.
  2. 使用 <object>: 不常見, 且使用者端的瀏覽器需要在安全性設定上將[使用指令碼片段](scriptlet) 設定為[啟用].
    使用指令碼片段
    Sample:
    <object width=100% height="100%" border="0" 
      type="text/x-scriptlet" data="http://www.w3schools.com/"></object>
  3. 透過 Javascript 使用 XMLHTTP: 在各個 AJAX 的教學網站中, 都會提到使用 Microsoft.XMLHTTP 或 XMLHttpRequest 物件去讀取其他網頁的資源.
    不過一樣會受限於瀏覽器的存取權限, 只能讀取同 domain 的網路資源.
    Sample:
    function displayResult(strUrl, displayOid) {
      try {
        //取得顯示資料的object
        var oDisplay = document.getElementById(displayOid);
        var xmlhttp = null;
        if (window.ActiveXObject) { // IE
          try {
            xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
          } 
          catch (e) {
            try {
              xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
            } 
            catch (e) {}
          }
        } 
        else if (window.XMLHttpRequest) { // Mozilla
          xmlhttp = new XMLHttpRequest();
          if (xmlhttp.overrideMimeType) {
            try {
              //設定MimeType(如果讀取有問題,加這一段或許可解決)
              xmlhttp.overrideMimeType('text/xml');
            } 
            catch (e) {}
          }
        }
         if (xmlhttp != null && oDisplay != null) {
          //設定讀取資料的事件處理函式
          xmlhttp.onreadystatechange = function() {
            if (xmlhttp.readyState == 4) {// 4 = "complete"
              if (xmlhttp.status == 200) {// 200 = "HTTP 200 OK"
                //將讀取到的字串設定至目的物件的innerHTML
                oDisplay.innerHTML = xmlhttp.responseText;
              }
            }
          };
          //第三個參數是設定是否要非同步(true:要,false:不要)
          xmlhttp.open("GET", strUrl, true);
          xmlhttp.send(null);
          //如果要用POST,參考以下附註的做法
          //var params = "id=1&subid=2";
          //xmlhttp.open("POST", strUrl, true);
          //xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
          //xmlhttp.setRequestHeader("Content-length", params.length);
          //xmlhttp.setRequestHeader("Connection", "close");
          //xmlhttp.send(params);
        }
        else {
          alert("你的瀏覽器不支源XMLHTTP");
        }
      }
      catch (e) {
        alert("錯誤:" + e.description);
      }
    }
  4. 寫一個泛型處理常式 (ashx) 來讀取遠端的檔案:
    其實一開始是想讓 B 網站的網頁 (html) 透過 Javascript 的方式讀取 A 網站的特定網頁, 不過一直卡在存取權限上只好換這樣的做法.
    1. 在 A 網站中新增一個泛型處理常式 (ex: ReadRemoteUrl.ashx).
    2. 在 ashx 裡將 context.Response.ContentType 設定為 "text/javascript", 程式碼如下:
      public class ReadRemoteUrl : IHttpHandler
      {
        public void ProcessRequest(HttpContext context)
        {
          //先將資料清空
          context.Response.Clear();
          context.Response.ClearHeaders();
          context.Response.ClearContent();
          //設定為Javascript
          context.Response.ContentType = "text/javascript";
          try
          {
            //判斷是否有指定的url要讀取
            if (!string.IsNullOrEmpty(context.Request["url"]))
            {
              //透過WebClient讀取資料,如果是讀xml,可以透過XmlDocument的Load()
              string strWebContent = string.Empty;
              using (System.Net.WebClient oClient = new System.Net.WebClient())
              {
                strWebContent = oClient.DownloadString(context.Request["url"]);
              }
              //"取代為\", '取代為\', NewLine取代為空字串
              string strContent = System.Text.RegularExpressions.Regex.Replace(
                strWebContent, "[\"']|(\\r\\n)", delegate(System.Text.RegularExpressions.Match m)
                {
                  switch (m.Value)
                  {
                    case "\"":
                      return "\\\"";
                    case "'":
                      return "\\'";
                    default:
                      return string.Empty;
                  }
                });
              //設定輸出內容的Encoding(預設UTF8)
              context.Response.ContentEncoding = System.Text.Encoding.UTF8;
              //判斷是否有指定的Encoding(這邊只分big5和utf8)
              if (!string.IsNullOrEmpty(context.Request["enc"]))
              {
                if (context.Request["enc"].Equals("big5", StringComparison.OrdinalIgnoreCase))
                {
                  context.Response.ContentEncoding = System.Text.Encoding.GetEncoding(950);
                }
              }
              //利用Javascript的document.write()將網頁資料輸出
              context.Response.Write("document.write(\"" + strContent + "\");");
            }
          }
          catch (Exception e)
          {
            context.Response.Clear();
          }
        }
         public bool IsReusable
        {
          get
          {
            return false;
          }
        }
      }
    3. 在 B 網站的網頁中可以使用 <script> 的方式進行呼叫, 例如: (讀取 http://www.w3schools.com/xsl/cdcatalog.xml)
      <!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">
      <head>
          <title>這是測試</title>
      </head>
      <body>
      <div id="divResult">
      <script type="text/javascript" 
      src="http://192.168.1.3/MyTest/ReadRemoteUrl.ashx?url=http://www.w3schools.com/xsl/cdcatalog.xml"></script>
      </div>
      </body>
      </html>
    Note: 讀取網頁內容一般是用在讀取 XML 或一些較簡單的網頁內容. 有點像是在嵌入一個小廣告之類的資料.  所以最好在 ashx 裡多加一些判斷, 例如只有某幾個介接網站可使用, 或是只能讀取特定的一些資源.

沒有留言: