iframe用src打开另一个html时,跨域报错问题避坑

需求描述: 项目中后端返回了一个html页面地址url,前端需要把这个html页面内容转成图片展示在页面中。

思路一: 最直接的就是在页面中用iframe打开这个url,打开后利用iframe的api'contentWindow.document.body获取需要的DOM,然后用html2canvas插件转成图片显示,同时iframe的样式属性diaplay设为none隐藏。

Bug问题描述: 想法好,现实很骨感,由于后端返回的url地址是跨域的,那肯定over了。 但是当与后端协商后,经处理,后端返回了同源地址,还是出现iframe跨域报错,无法解决!!!

跨域时,共有三种行为受到限制:

  • Cookie、LocalStorage和IndexDB无法读取。
  • DOM无法获取。
  • AJAX请求不能发送。

解决思路: 既然用iframe的src无法打开,且神奇地发现只放了iframe,打印其DOM时,其document内部结构存在; 想到是否可以试试把后端返回的链接中的,html插入到iframe中的body下。
一试果然可以,反正我们用ifame的主要目的其实是开另一个小窗口,且在html2canvas截图时起到窗口作用(截图不至于跑偏出现白边)
在这里插入图片描述
在这里插入图片描述

  1. 获取iframe DOM下的body节点
const iframe = this.$refs["iframe" + index];
const ibody = iframe[0].contentWindow.document.body;
  1. axios请求url地址拿到html代码,(axios解决跨域问题自行搜查)
  2. 使用innerHTML把获取的html插入body节点
  3. 使用html2canvas进行截图存图,隐藏iframe
    示例代码Vue项目:
    html部分:
<div
  v-for="(item, index) in informationData"
  :key="index"
  v-loading="item.loading"
  class="iframeBox"
   >
    <iframe
     :ref="'iframe' + index"
     class="iframe"
     frameborder="0"
     ></iframe>
</div>
//informationData是后端另一个接口返回的含需要请求的html页面地址的数据
//结构类似:[{name:"xxxx", link:"http://xxxxx"}]

js部分:

openImg(item, index) {
      const _this = this;
      item.loading = true;
      const iframe = this.$refs["iframe" + index];
      const ibody = iframe[0].contentWindow.document.body;
      axios.get(item.link).then(res => {
        ibody.innerHTML = res.data;
        _this.$nextTick(() => {
          html2canvas(ibody, {
            allowTaint: true,
            useCORS: true,
            scale: 2,
            logging: false
          }).then(canvas => {
            const imgBase64 = canvas.toDataURL("image/png");
            if (imgBase64) {
              item.loading = false;
              iframe[0].parentElement.style.display = "none";
              _this.imgArray.push({
                name: item.name,
                url: imgBase64
              });
            } else {
              console.log("image transfer failed");
            }
          });
        });
      });
    }
在使用iframe加载跨域资源,浏览器会使用同源策略进行限制,因此需要使用代理页面来解决跨域问题。ASP.NET中可以使用aspx页面来作为代理页面。 具体步骤如下: 1. 在项目中添加一个aspx页面,例如Proxy.aspx。 2. 在Proxy.aspx.cs文件中编写一个处理请求的方法,例如GetResource()。 3. 在GetResource()方法中使用WebRequest对象向目标资源发起请求,并获取响应数据。 4. 将响应数据返回给前端页面。 5. 在前端页面中使用iframesrc属性指定代理页面的地址,并将目标资源的地址作为参数传递给代理页面。 6. 在代理页面中获取目标资源的地址,并在GetResource()方法中使用该地址发起请求。 7. 将响应数据返回给前端页面,并在前端页面中使用iframe加载响应数据。 示例代码如下: Proxy.aspx.cs: ```csharp protected void Page_Load(object sender, EventArgs e) { // 获取目标资源的地址 string url = Request.QueryString["url"]; // 发起请求并获取响应数据 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); HttpWebResponse response = (HttpWebResponse)request.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8); string data = reader.ReadToEnd(); // 将响应数据返回给前端页面 Response.Clear(); Response.Write(data); Response.End(); } public void GetResource(string url) { // 构造代理页面的地址 string proxyUrl = "http://localhost:8080/Proxy.aspx?url=" + url; // 使用iframe加载代理页面 var iframe = document.createElement("iframe"); iframe.src = proxyUrl; document.body.appendChild(iframe); } ``` 前端页面: ```html <body> <script> GetResource("https://example.com/resource"); </script> </body> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值