WebGL自學課程(7):WebGL載入跨域紋理出錯Cross-origin image load denied by Cross-Origin Resource Sharing policy.
阿新 • • 發佈:2019-02-09
最近在學習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;
}
}
}