坑一、是不是函數重名的問題
如圖報了一個這樣的錯,百度好多都說是函數名和html元素重名的問題。可是這個問題我想我這里是不存在的
可以看到就一個綁定事件,而且id名不是關鍵字
報錯是在$.ajax這一行,索性就把submit-info改了吧,但是還是沒有用。
坑二、是不是跨域的問題
看錯誤 6處錯誤,有5行是jQuery.js的錯誤,有一處是涉及到我自己寫的js錯誤
問題就在這了:at HTMLButtonElement.<anonymous>
也就是canvas加載服務器圖片,沒有允許跨域造成的。
關於跨域,百度的解決方案有很多。
首先普及一下知識。CORS是一個W3C標准,全稱是"跨域資源共享"(Cross-origin resource sharing)。CORS需要瀏覽器和服務器同時支持。目前,所有瀏覽器都支持該功
能,IE瀏覽器不能低於IE10。
它允許瀏覽器向跨源服務器,發出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。整個CORS通信過程,都是瀏覽器自動完成,不需要用戶參與。對於開發者來
說,CORS通信與同源的AJAX通信沒有差別,代碼完全一樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有
感覺。因此,實現CORS通信的關鍵是服務器。只要服務器實現了CORS接口,就可以跨源通信。
請求流程
1、preflight request發送請求
2、preflight Response返回一些信息,驗證是否允許跨域,接而執行步驟3和4
這里是被請求的服務器后端允許請求端請求資源,才能實現跨域。
因此,我們需要在被請求的服務器端方法內允許對方請求,加入如下代碼
response.setHeader("Access-Control-Allow-Origin", "http://localhost:9105");
response.setHeader("Access-Control-Allow-Credentials", "true");
如果是SpringMVC4.2及以上的版本,則可以直接使用注解
@CrossOrigin(origins="http://localhost:9105",allowCredentials="true")
這個注解 allowCredentials="true" 默認為true,所以可以不寫。
可以看到這兩句代碼主要是給請求方set一個header
Access-Control-Allow-Origin 設置被允許請求的源,如果是允許所有源請求,設置為 *
Access-Control-Allow-Credentials 設置是否允許發送cookie
Access-Control-Allow-Origin是HTML5中定義的一種解決資源跨域的策略。
他是通過服務器端返回帶有Access-Control-Allow-Origin標識的Response header,用來解決資源的跨域權限問題。
CORS請求默認不發送Cookie和HTTP認證信息。如果要把Cookie發到服務器,一方面要服務器同意,指定Access-Control-Allow-Credentials字段。另一方面,開發者必須在AJAX請求中打開
withCredentials屬性。否則,即使服務器同意發送Cookie,瀏覽器也不會發送。或者,服務器要求設置Cookie,瀏覽器也不會處理。
'withCredentials':true
坑三、后端解決同源
可以嗎?然並卵。其實到這里,我的問題自己也清楚了。因為我用的是獨立的文件服務器fastDFS存儲圖片,那么我的前端是通過代理訪問了圖片服務器。如果要加CrossOrigin,那么需要在tracker
設置。顯然不可能。所以我的解決方案是在后台把圖片轉成base64格式傳遞給前端,這樣就達到了同源。java代碼如下:
import sun.misc.BASE64Encoder; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; /** * 將文件服務器圖片編碼為Base64 * @param url * @return * @throws Exception */ public static String encodeImageToBase64(URL url) throws Exception { //將圖片文件轉化為字節數組字符串,並對其進行Base64編碼處理 System.out.println("圖片的路徑為:" + url.toString()); //打開鏈接 HttpURLConnection conn = null; try { conn = (HttpURLConnection) url.openConnection(); //設置請求方式為"GET" conn.setRequestMethod("GET"); //超時響應時間為5秒 conn.setConnectTimeout(5 * 1000); //通過輸入流獲取圖片數據 InputStream inStream = conn.getInputStream(); //得到圖片的二進制數據,以二進制封裝得到數據,具有通用性 ByteArrayOutputStream outStream = new ByteArrayOutputStream(); //創建一個Buffer字符串 byte[] buffer = new byte[1024]; //每次讀取的字符串長度,如果為-1,代表全部讀取完畢 int len = 0; //使用一個輸入流從buffer里把數據讀取出來 while ((len = inStream.read(buffer)) != -1) { //用輸出流往buffer里寫入數據,中間參數代表從哪個位置開始讀,len代表讀取的長度 outStream.write(buffer, 0, len); } //關閉輸入流 inStream.close(); byte[] data = outStream.toByteArray(); //對字節數組Base64編碼 BASE64Encoder encoder = new BASE64Encoder(); String base64 = encoder.encode(data); System.out.println("網絡文件[{}]編碼成base64字符串:[{}]"+url.toString()+base64); return base64;//返回Base64編碼過的字節數組字符串 } catch (IOException e) { e.printStackTrace(); throw new Exception("圖片讀取失敗,請聯系客服!"); } }
什么前端圖片加載不出來,what?這個base64是純字符串,請給它加上22位前綴data:image/png;base64,
img.src="data:image/png;base64,"+base64;
坑四、js版本的問題
然而問題還在繼續,但是這次有進展能向后台發送請求了,只是ajax請求的data參數是Object
最后問題找到在ajax傳遞的參數中用了關鍵字 length和width,但是奇怪的是上一個頁面用的相同的方法就行,這個頁面就不行了。
上個頁面只是多了個form表單,好吧閑話不多說。在html中把關鍵字改名,ajax提交成功了,進了后台。
但是問題又來了,后台接收不到數據,走了很多彎路。解決辦法是把jquery-3.3.1.min.js換成jquery-1.8.3.min.js
搞定
真是一波三折啊,程序猿一般人真干不了!