現象
首先,在生產環境中,由于進行編輯圖片時,將圖片回顯到ReactCrop組件中進行可裁剪編輯,然而回顯時,需要將圖片轉化為base64的格式或者blob物件, 此時需要將圖片次繪制成canvas進行裁剪,但是,就會出現圖片的跨域問題,圖片不在一個域下的話,使用 canvas 會污染畫布,所以就不行啦!!!!
不過這個其實是需要后端在服務端進行配置就好了,但是前端要硬抗的話,那只能含著淚解決吧!
解決方案一
因為在本地進行圖片回顯的時候就已經跨域了,所以為了保證在同一域的環境進行處理圖片顯示的問題,
Mac
- 設定打開Chorme跨域瀏覽器指令:
open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/${電腦用戶名}/MyChromeDevUserData/
注意: 運行命令之前,必須得徹底關閉當前chorme瀏覽器,
例如:open -n /Applications/Google\ Chrome.app/ --args --disable-web-security --user-data-dir=/Users/gml/MyChromeDevUserData/
Windows
- Chrome 49 以后版本
--disable-web-security --user-data-dir=<用戶資料路徑> --allow-file-access-from-files
- 完整例子
C:\Users\Administrator\AppData\Local\Google\Chrome\Application\chrome.exe --disable-web-security --user-data-dir=C:\MyChromeDevUserData --allow-file-access-from-files
- 創建 Chrome 快捷方式,在目標一欄后面添加引數即可

以上是設定跨域瀏覽器的教程,下面回歸正題
getBase64 = (url, callback)=> {
const urlReplace = url.replace('http', 'https');
//通過建構式來創建的 img 實體,在賦予 src 值后就會立刻下載圖片,相比 createElement() 創建 <img> 省去了 append(),也就避免了檔案冗余和污染
/*let img = new Image(),
dataURL = '';
img.crossOrigin = "Anonymous";
img.src = url;
img.onload = function () { //要先確保圖片完整獲取到,這是個異步事件
let canvas = document.createElement('canvas'), //創建canvas元素
width = img.width, //確保canvas的尺寸和圖片一樣
height = img.height;
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(img, 0, 0, width, height); //將圖片繪制到canvas中
dataURL = canvas.toDataURL('image/jpeg'); //轉換圖片為dataURL
callback && callback(dataURL); //呼叫回呼函式
};*/
console.log('urlReplace', urlReplace)
const _this = this;
axios.get(urlReplace,
{
responseType: 'blob',
headers: { "Access-Control-Allow-Origin": "*" }
}
).then(function (response) {
console.log('response', response)
_this.callBack(response);
})
}
callBack(res){
let blob = new Blob([res]);
let url = window.URL.createObjectURL(blob);
console.log('url', url);
this.setState({
src: url
})
// 釋放url物件
// window.URL.revokeObjectURL(url);
}
以上的原始代碼在在轉化base64時,需要canvas重繪圖片,進行生成base64圖片格式進行接收,也就是toDataURL()是canvas物件的一種方法,用于將canvas物件轉換為base64位編碼,但是出現是canvas.tuDataUrl的跨域問題,
- 將圖片轉換為base64位編碼有什么好處?
1、將圖片轉換為base64位編碼后,圖片會跟隨代碼(html、css、js)一起請求加載,不會再單獨進行請求加載; 2、可以防止由于圖片路徑錯誤導致圖片加載失敗的問題;
使用canvas.toDataUrl跨域的解決方式就是在設定img.crossOrigin = “Anonymous”; 方法,然后在服務器端設定請求頭"Access-Control-Allow-Origin": “*”,然而在生產環境并無效果,所以避開canvas的跨域問題只能重新更換方案,
補充:
- img元素中的crossorigin屬性
img是我們在web開發中比較常用的一個標簽,它代表著檔案中的一個影像元素,HTML5給這個標簽新增加了一個crossorigin屬性,這個屬性決定了圖片獲取程序中是否開啟CORS功能
使用場景
在最近的專案開發中,在前端預覽圖片并讓用戶裁剪,再將裁剪好的圖片上傳到后端的服務器上,這里輸入的圖片地址很有可能來自第三方站點,這就涉及到一個跨域的問題,如果僅僅是展示預覽圖片的話是沒有什么問題的,但這里裁剪圖片時需要將裁剪好的圖片進行base64編碼,如果沒有使用crossorign開啟CORS功能的話,在使用canvas的toBlob()、toDataURL()和getImageData()方法時就會出現跨域的問題,
crossorigin屬性
這個屬性有兩個值可選:
anonymous:如果使用這個值的話就會在請求中的header中的帶上Origin屬性,但請求不會帶上cookie和其他的一些認證資訊,
use-credentials:這個就同時會在跨域請求中帶上cookie和其他的一些認證資訊,
在使用這兩個值時都需要server端在response的header中帶上Access-Control-Allow-Credentials屬性,
雖然 已經設定但是在生產環境還未生效,這可能是后端的鍋了,不過后端一直沒有改好的情況下,前端只能硬著頭皮去抗下啦,還好經過百般嘗試后,出來了解決方案:
getBase64 = (url, callback)=> {
const urlReplace = url.replace('http', 'https');
const _this = this;
axios.get(urlReplace,
{
responseType: 'blob',
headers: { "Access-Control-Allow-Origin": "*" }
}
).then(function (response) {
console.log('response', response)
_this.callBack(response);
})
}
callBack(res){
let blob = new Blob([res]);
let url = window.URL.createObjectURL(blob);
console.log('url', url);
this.setState({
src: url
})
// 釋放url物件
// window.URL.revokeObjectURL(url);
}
以上代碼通過axios請求圖片路徑并且加上請求頭的條件,然后回傳結果生成Blob物件,然后再創建 URL 的blob物件,賦值到裁剪的組件里進行實時裁剪,
總結:
以上嘗試的結果,也是避開canvas的跨域問題,另起爐灶開辟了新的方案,才解決了跨域的根本問題,不過解決辦法還有其他方式,后續可以深入研究
以上解決的問題中涉及的知識點也蠻多的:
- canvas的toDataUrl跨域問題canvas的toDataUrl跨域問題
- crossorigin屬性 crossorigin
- Cross-Origin Resource Sharing(CORS)解決方案CORS
- axios的請求方式 axios
- toDataURL()方法 toDataURL()方法
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/223567.html
標籤:其他
上一篇:制作投影:3D 模型法
下一篇:【實用教程】網課視頻自動播放代碼
