【问题标题】:JavaScript Image blocked by CORSJavaScript 图像被 CORS 阻止
【发布时间】:2018-12-30 10:24:02
【问题描述】:

我在下面有这段代码,它由一个 HTML 选项卡和一个模式组成,我在下面所做的是我使用库 HTML2Canvas 来捕获选定的 divs。但问题是当我单击下载时,它不会在我下载的文件中捕获图像。

一直有这个错误Access to Image at '//IMAGE LINK' from origin 'http://localhost' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

我尝试将 crossorigin:anonymous 添加到我的 img 中,但仍然没有运气。有没有简单的方法来解决这个问题?任何帮助将不胜感激。

function sendData() {


  $('#myModal2').addClass('modal-posit');

  var modalButton = $('[data-target="#myModal2"]')[0];
  modalButton.click();
  var modal = $('#myModal2')[0];
  


  setTimeout(function() {
    html2canvas(document.getElementById('capture'), {
      allowTaint: false,
      useCORS: true
    }).then(function(canvas) {
        downloadCanvas(document.getElementById('test'), canvas, 'test.png');
        modalButton.click();
    });
  }, 1000);
}

function openCity(evt, cityName) {
  var i, tabcontent, tablinks;
  tabcontent = document.getElementsByClassName("tabcontent");
  for (i = 0; i < tabcontent.length; i++) {
    tabcontent[i].style.display = "none";
  }
  tablinks = document.getElementsByClassName("tablinks");
  for (i = 0; i < tablinks.length; i++) {
    tablinks[i].className = tablinks[i].className.replace(" active", "");
  }
  document.getElementById(cityName).style.display = "block";
  evt.currentTarget.className += " active";
}

function downloadCanvas(link, canvas, filename) {
    link.href = canvas.toDataURL();
    link.download = filename;
    link.click();
}

document.getElementById("defaultOpen").click();
body {
  font-family: Arial;
}

.tab {
  overflow: hidden;
  border: 1px solid #ccc;
  background-color: #f1f1f1;
  margin-top: 10px;
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
}


/* Style the buttons inside the tab */

.tab button {
  background-color: inherit;
  float: left;
  border: none;
  outline: none;
  cursor: pointer;
  padding: 14px 16px;
  transition: 0.3s;
  font-size: 17px;
  border-bottom: 8px;
}


/* Change background color of buttons on hover */

.tab button:hover {
  background-color: #ddd;
}


/* Create an active/current tablink class */

.tab button.active {
  background-color: #ccc;
}


/* Style the tab content */

.tabcontent {
  display: none;
  padding: 6px 25px;
  border: 1px solid #ccc;
  border-top: none;
  -webkit-animation: fadeEffect 1s;
  animation: fadeEffect 1s;
  border-bottom-left-radius: 8px;
  border-bottom-right-radius: 8px;
  background-color: white;
}

.jobs-panel {
  display: table;
  max-height: 100%;
  width: 85%;
  background-color: #b7bcbe;
  margin-left: auto;
  margin-right: auto;
  margin-top: 25px;
  margin-bottom: 25px;
  padding-bottom: 20px;
  padding-top: 20px;
}

.tabwidth {
  width: 85%;
  margin: 0 auto;
}
.modal-posit{
  position: relative;
}
<!DOCTYPE html>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<html>

<head>
    <meta charset="utf-8" />
    <style>


    </style>
    <link rel="shortcut icon" href="//#" />
    <script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.js"></script>
    <script type="text/javascript" src="https://html2canvas.hertzen.com/dist/html2canvas.min.js"></script>
</head>

<body>
    <div id="capture">
    

      <div class="jobs-panel">
  
        <button class="modal-button" data-toggle="modal" data-target="#myModal2">MODAL BUTTON</button>
  
        <div class="tabwidth">
          <div class="tab">
            <button class="tablinks" onclick="openCity(event, 'Graph')" id="defaultOpen">Graph</button>
          </div>
  
          <div id="Graph" class="tabcontent">
            <img src="https://s3-ap-southeast-1.amazonaws.com/investingnote-production-webbucket/attachments/41645da792aef1c5054c33de240a52e2c32d205e.png" width="300" height="300" >
          </div>
  
          <div id="Paris" class="tabcontent">
            <h3>Paris</h3>
            <p>Paris is the capital of France.</p>
          </div>
  
          <div id="Tokyo" class="tabcontent">
            <h3>Tokyo</h3>
            <p>Tokyo is the capital of Japan.</p>
          </div>
        </div>
      </div>
      <div class="modal fade" id="myModal2" role="dialog">
        <div class="modal-dialog modal-lg">
          <div class="modal-content">
            <div class="modal-header">
              <button type="button" class="close" data-dismiss="modal">&times;</button>
              <h2 class="modal-title center">FAQ</h2>
            </div>
            <div class="modal-body">
              <div class="central">
                <h3 class="bold-text ">QUESTIONS
                </h3>
              </div>
            </div>
            <div class="modal-footer">
              <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            </div>
          </div>
        </div>
      </div>
    </div>
 
    <button id="match-button" onclick="sendData();">capture</button>
    <a id="test" href="#"></a>
  </body>
</html>

<script>

</script>

【问题讨论】:

  • 这是您的图片,还是您尝试使用来自其他网站但不属于您的图片?
  • @TylerRoper 是的,我正在尝试使用来自不同站点的图像,但它也来自 amazonaws
  • 除非这是您的域并且您有能力更改图像本身的标题,否则您无能为力。欲了解更多信息,read here:“尽管您可以在画布中使用未经 CORS 批准的图像,但这样做会污染画布。一旦画布被污染,您就不能再提取数据退出画布。例如,您不能再使用画布 toBlob()、toDataURL() 或 getImageData() 方法;这样做会引发安全错误。"
  • @TylerRoper 域与 aws 帐户一样吗?
  • @Tommy - Tyler 在这里做了一个小的概括。您无需拥有或控制图像来自的域即可使用 CORS。但是,您需要控制图像来自的服务器。如果您确实可以控制该服务器,请阅读特定文档(Nginx、PHP、Node.js、Java、Tomcat、Apache、Ruby-on-rails 等),了解哪些软件正在为该图像提供服务,以了解如何启用 CORS .不幸的是,CORS 是服务器,而不是浏览器(尽管浏览器是执行 CORS 的实体)

标签: javascript html cors html2canvas


【解决方案1】:

图像的 CORS 权限需要 BOTH 服务器 和 浏览器 才能执行某些操作。

首先浏览器必须请求CORS权限。

您可以通过在图像上设置crossOrigin 来做到这一点。示例

const img = new Image();
img.crossOrigin = "anonymous";
img.src = "https://somesite.com/someimage.jpg"

请注意,crossOrigin 有 3 个有效值。

  1. 未定义

    这意味着浏览器不会请求 CORS 权限,也不会检查标头。即使服务器发送标头,您仍然会收到安全错误,具体取决于您尝试对来自另一个域的图像执行的操作。这是默认设置。

  2. '使用凭据'

    这意味着浏览器将向服务器发送额外信息(cookie 等),以便它可以用来决定是否授予权限。

  3. 其他的

    您可以输入“”或“匿名”或“foobarmoo”或任何其他内容。如果它不是未定义的并且不是“使用凭据”,那么它就是第三个版本。这意味着在没有任何额外信息的情况下请求一揽子 CORS 许可。

其次,服务器必须发送正确的标头。

如果您控制服务器,则需要对其进行配置以发送正确的标头。每台服务器都是不同的(apache、nginx、caddy 等)。每台服务器都不同,如果您想知道如何配置该特定服务器,您应该在该服务器的文档中查找它或询问该服务器的特定问题。

默认情况下,大多数服务器不发送 CORS 标头。此外,大多数第 3 方网站不发送图像的 CORS 标头。 3 个例外是 imgur、github pages 和 flickr(遗憾的是至少截至 2018 年 7 月还没有 stack.imgur)。如果您尝试从网络上的随机服务器访问图像,那么您很不走运,只能联系他们的客户支持并要求他们添加标题。

在您的情况下,您正在访问 AWS 上的图像。 AWS 上的服务器未发送 CORS 标头。您的解决方案是 (a) reconfigure AWS to send CORS headers 如果您可以控制那里的服务器 (b) 询问控制该服务器的人添加 CORS 标头 (c) 意识到没有 (a) 或 (b) 就无法做您想做的事情.

这是一个演示:我们将尝试加载您的图像,一张来自 imgur 的图像(确实设置了 cors 标题)和另一张 imgur 但未设置 crossOrigin 以显示 BOTH 设置 @ 987654328@ AND 需要接收 cors 标头。

loadAndDrawImage("https://s3-ap-southeast-1.amazonaws.com/investingnote-production-webbucket/attachments/41645da792aef1c5054c33de240a52e2c32d205e.png", "anonymous");
loadAndDrawImage("https://i.imgur.com/fRdrkI1.jpg", "anonymous");
loadAndDrawImage("https://i.imgur.com/Vn68XJQ.jpg");

function loadAndDrawImage(url, crossOrigin) {
  const img = new Image();
  img.onload = function() { 
    log("For image", crossOrigin !== undefined ? "WITH" : "without", "crossOrigin set:", url);
    try {
      const ctx = document.createElement("canvas").getContext("2d");
      ctx.drawImage(img, 0, 0);
      ctx.getImageData(0, 0, 1, 1);
      success("canvas still clean:", url);
    } catch (e) {
      error(e, ":", name);
    }
    log(" ");
  };
  img.onerror = function(e) {
    error("could not download image:", url);
    log(" ");
  };
  if (crossOrigin !== undefined) {
    img.crossOrigin = crossOrigin;
  }
  img.src = url;
}

function logImpl(color, ...args) {
  const elem = document.createElement("pre");
  elem.textContent = [...args].join(" ");
  elem.style.color = color;
  document.body.appendChild(elem);
}

function log(...args) {
  logImpl("black", ...args);
}

function success(...args) {
  logImpl("green", ...args);
}

function error(...args) {
  logImpl("red", ...args);
}
pre { margin: 0; }
<pre>check headers in devtools

</pre>

PS:还有另一种解决方案,但可以说是粗略的。您可以运行代理服务器,从 AWS 下载图像,然后将其发送到添加了 CORS 标头的页面(或从与页面相同的域发送)。我怀疑这就是您正在寻找的解决方案。

【讨论】:

  • 感谢您的信息!我看到 html2canvas 有代理或其他东西,但我不确定如何使用它。 html2canvas.hertzen.com/proxy 这是我需要下载的东西吗?
  • 如果您希望能够使用来自您无法控制且未设置 CORS 标头的服务器的图像,那么可以,您可以使用您链接到的代理服务器。您需要将其设置在某处的服务器上(您的个人计算机、AWS 或 Digital Ocean 上的服务器或......)。它是如何设置的,这对 SO 来说是个大问题。 try Google
猜你喜欢
  • 2020-11-11
  • 2019-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-11
  • 2021-04-16
  • 2015-10-09
  • 2018-10-18
相关资源
最近更新 更多