前言
需求是在h5商城增加商品海报分享功能,海报包含商品活动信息,商品本身信息。
一、问题表现
在保存海报之后,部分手机可显示图片,部分商品可正常显示图片
二、定位问题及解决问题过程中使用的方法
1.纯前端
控制台报因为cors策略图片跨域的错误,在网上找到了关于前端图片跨域解决的办法
方法1将跨域图片下载下来转换为base 64格式存在本地,然后转换路径,将需要展示的dom元素原本的网络路径改为本地存贮路径,以下是代码
async getBase64(imgUrl) {
return new Promise((reslove, reject) => {
try {
let xhr = new XMLHttpRequest();
xhr.open("get", imgUrl, true);
// 重点1
xhr.responseType = "blob";
xhr.onload = function () {
console.log("请求完成时触发", this);
if (this.status == 200) {
//得到一个blob对象
let blob = this.response;
// 重点2
let oFileReader = new FileReader();
oFileReader.onloadend = function (e) {
// 结果
const base64 = e.target.result;
document.getElementById("imgUrlId").children[1].src = base64;
// console.log('查看所有子节点',document.getElementById("imgUrlId").children)
//将网络路径转换为本地图片路径
document.getElementById(
"imgUrlId"
).children[0].style.backgroundImage = `url(${base64})`;
reslove(true);
};
oFileReader.readAsDataURL(blob);
} else {
console.log("getbase64", this);
}
};
xhr.onreadystatechange = function () {
console.log("xhr.readyState值改变触发", xhr.readyState);
};
xhr.onloadstart = function () {
console.log("调用send后立即触发", xhr);
};
xhr.onloadend = function () {
console.log("请求结束(成功或失败触发)", xhr.readyState);
};
xhr.onerror = function (err) {
console.log(
"出现错误",
err,
"xhr.statusText",
xhr.statusText,
"xhr.readyState",
xhr.readyState
);
};
xhr.send();
} catch (e) {
console.log("查看抛出异常", e);
}
});
},
但是发现个很坑的事情,本身这个域名请求网络图片地址就报错跨域了,用原生的xhr请求不是一样的也会报跨域,这点在pc端启动项目是不会体现错误的,后面一发布到h5端运行就展示不出图片,找了一会,发现两个错误,一个是报错图片跨域,这个好理解,如下图:
这个是因为uni-app的image标签不是一个单纯的dom元素,是一个服务器控件,经过编译后会
变成多层标签嵌套,如下图:
会变成一个含有背景图片的div包裹着img,显示的也是div。
然后紧接着在网络请求中发现了另外一个奇怪的错误,如下图:
后面查阅了资料,更加确定是跨域问题
请求状态码为0的几种可能(如有补充,欢迎留言):
1.xhr请求的路径有误
2.网络问题
3.检查防火墙拦截
4.请求跨域
然后在配置跨域的时候,cors同源策略需要后端配合,但问了我这边的后端大牛,项目是直接请求阿里云的oss静态资源托管,没有走后端自己的接口,本来挺苦恼的,转念一想,既然直接走的oss,又报错cors,是不是阿里云原本就有关于cors的配置项?
2.通过修改oss配置
后面登录oss控制台,果然查询到有关于cors的配置项(注意:配置后需要过一段时间生效)
一般来说配成这样就可以,这个表示允许所有来源访问,如果希望指定来源访问的话前端需要在请求的时候带上请求头,和配置保持一致,再一个就是暴露Headers里的需要配置,里面的Etag表示访问失败的抛出错误信息。