背景:dom中img src 为项目本地路径,本地调试时调用dom-to-image toPng方法时,可以正常生成截图,但线上调试时提示:Cross origin requests are only supported for HTTP.
XMLHttpRequest cannot load file:///var/mobxxxxxxx
按照提示,这个应该是跨域问题,但在调用方法时,我明明已经开启了useCORS: true
断点查看调用栈显示在XMLHttpRequest这里出了问题:
cannot load file:///var/mobile/Containers/Data/Application/3AD80DAD-368A-4F7A-A553-EDD9CBFA3028/Documents/xxxx/mPaaS/xxxx/xxxx/static/media/xxxx.17ad6194.png due to access control checks.
function getAndEncode(url) {
var TIMEOUT = 30000;
if(domtoimage.impl.options.cacheBust) {
// Cache bypass so we dont have CORS issues with cached images
// Source: https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Bypassing_the_cache
url += ((/\?/).test(url) ? "&" : "?") + (new Date()).getTime();
}
return new Promise(function (resolve) {
var request = new XMLHttpRequest();
request.onreadystatechange = done;
request.ontimeout = timeout;
request.responseType = 'blob';
request.timeout = TIMEOUT;
request.open('GET', url, true);
request.send();
var placeholder;
if(domtoimage.impl.options.imagePlaceholder) {
var split = domtoimage.impl.options.imagePlaceholder.split(/,/);
if(split && split[1]) {
placeholder = split[1];
}
}
function done() {
if (request.readyState !== 4) return;
if (request.status !== 200) {
if(placeholder) {
resolve(placeholder);
} else {
fail('cannot fetch resource: ' + url + ', status: ' + request.status);
}
return;
}
var encoder = new FileReader();
encoder.onloadend = function () {
var content = encoder.result.split(/,/)[1];
resolve(content);
};
encoder.readAsDataURL(request.response);
}
function timeout() {
if(placeholder) {
resolve(placeholder);
} else {
fail('timeout of ' + TIMEOUT + 'ms occured while fetching resource: ' + url);
}
}
function fail(message) {
console.error(message);
resolve('');
}
});
}
解决方案1:img标签里的图片改为url加载
<img src:'url'></img>
解决方案2:img标签里的图片改为base64加载
<img src:'base64'></img>
原理
方案1:通过http链接加载,正常完成XMLHttpRequest请求逻辑
方案2:让newImage 方法在进入isDataUrl判断后,直接返回,不在进入XMLHttpRequest逻辑
function newImage(element) {
return {
inline: inline
};
function inline(get) {
if (util.isDataUrl(element.src)) return Promise.resolve();
return Promise.resolve(element.src)
.then(get || util.getAndEncode)
.then(function (data) {
return util.dataAsUrl(data, util.mimeType(element.src));
})
.then(function (dataUrl) {
return new Promise(function (resolve, reject) {
element.onload = resolve;
element.onerror = reject;
element.src = dataUrl;
});
});
}
}
网友评论