1. 程式人生 > >WebGL自學課程(7):WebGL載入跨域紋理出錯Cross-origin image load denied by Cross-Origin Resource Sharing policy.

WebGL自學課程(7):WebGL載入跨域紋理出錯Cross-origin image load denied by Cross-Origin Resource Sharing policy.

最近在學習WebGL,用圖片對WebGL進行紋理貼圖,其中圖片是從其他網站跨域獲取的,用Chrome 22執行網頁,開始的時候出現了錯誤Uncaught Error: SECURITY_ERR: DOM Exception 18

Cross-origin image load denied by Cross-Origin Resource Sharing policy.

此錯誤也就說明我們不能使用跨域圖片作為紋理,既然不能將跨域圖片用作WebGL紋理,那麼我就想到了先把圖片儲存到和我們執行的網頁相同的目錄下,然後再載入這個本地圖片,這樣就可以解決問題了。

具體的做法是:

假設我現在執行WebGL的網頁是demo.html,放置在LearningWebGL這個資料夾下。我們現在要解決的問題是在demo.html中用WebGL使用跨域獲得的圖片作為紋理,假設我們已經知道了要使用的跨域圖片的url。

我的做法是,在LearningWebGL資料夾下建立一個代理檔案proxy.ashx,然後在demo.html中用ajax將跨域圖片的url非同步傳送到proxy.ashx中,然後讓proxy.ashx獲取圖片並儲存到LearningWebGL資料夾下,假如將其命名為imageName,此時的遠端圖片已經下載到了本地,而且是和demo.html位於同目錄下。最後將圖片名imageName作為ajax的響應進行輸出。這樣我們在demo.html的ajax執行成功後通過responseText即可獲得本地的圖片的名稱。然後將WebGL紋理圖片的src設定為對應的本地圖片名稱imageName即可。

以下是前端的ajax程式碼:

function storeMapImage(imageUrl){
            var xmlHttpRequest = getXmlHttpRequest();
            if (xmlHttpRequest == null) {
                alert("您的瀏覽器不支援XMLHttpRequest");
            } else {
                xmlHttpRequest.onreadystatechange = function () {
                    if (xmlHttpRequest.readyState == 4 && xmlHttpRequest.status == 200) {
                        alert("完成!");
                        heightMap.initTextureImageUrl(xmlHttpRequest.responseText);
                    }
                };
                xmlHttpRequest.open("GET", "proxy.ashx?imageUrl="+imageUrl, true);
                xmlHttpRequest.send();
            }
        }

以下是程式碼檔案proxy.ashx的程式碼:
<%@ WebHandler Language="C#" Class="proxy" %>

using System;
using System.IO;
using System.Web;
using System.Drawing;

public class proxy : IHttpHandler 
{
    public void ProcessRequest(HttpContext context)
    {
        string url = context.Request["imageUrl"];
        System.Net.WebRequest request = System.Net.WebRequest.Create(new Uri(url));
        request.Method = context.Request.HttpMethod;
        request.ContentType = "application/x-www-form-urlencoded";

        System.Net.WebResponse response = request.GetResponse();
        Stream stream = response.GetResponseStream();
        Image img = Image.FromStream(stream);

        int index = url.LastIndexOf('/');
        string imageName = url.Remove(0, index+1);
        string baseDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
        string physicPath = baseDirectory + imageName;
        img.Save(physicPath);
		context.Response.Write(imageName);
        context.Response.End();
    }
 
    public bool IsReusable 
    {
        get {
            return false;
        }
    }
}