最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - JavaScript Image blocked by CORS - Stack Overflow

programmeradmin0浏览0评论

I have this code below that consists of a HTML Tab and a modal what i have done below is that i used the library HTML2Canvas to capture the selected divs. But the problem is when i click download it doesn't capture the image in my downloaded file.

It keeps having this error 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.

I have tried to add crossorigin:anonymous to my img but still no luck. Is there an easy way to solve this? any help would be greatly appreciated.

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=".3.1/jquery.min.js"></script>
<link rel="stylesheet" href=".3.7/css/bootstrap.min.css">
<script src=".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=".js"></script>
    <script type="text/javascript" src=".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=".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>

I have this code below that consists of a HTML Tab and a modal what i have done below is that i used the library HTML2Canvas to capture the selected divs. But the problem is when i click download it doesn't capture the image in my downloaded file.

It keeps having this error 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.

I have tried to add crossorigin:anonymous to my img but still no luck. Is there an easy way to solve this? any help would be greatly appreciated.

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>

Share Improve this question edited Jul 23, 2018 at 3:07 Andrew Marshall 97k20 gold badges227 silver badges217 bronze badges asked Jul 23, 2018 at 2:08 Best JeanistBest Jeanist 1,1294 gold badges14 silver badges36 bronze badges 5
  • Is this your image, or are you trying to use one from a different site that is not yours? – Tyler Roper Commented Jul 23, 2018 at 2:14
  • @TylerRoper Yes i'm trying to use a image from a different site but it's also from amazonaws – Best Jeanist Commented Jul 23, 2018 at 2:15
  • Unless this is your domain and you have the ability to change the headers on the image itself, you can't do anything about it. For more information, read here: "Although you can use images without CORS approval in your canvas, doing so taints the canvas. Once a canvas has been tainted, you can no longer pull data back out of the canvas. For example, you can no longer use the canvas toBlob(), toDataURL(), or getImageData() methods; doing so will throw a security error." – Tyler Roper Commented Jul 23, 2018 at 2:19
  • @TylerRoper domain as in the aws account? – Best Jeanist Commented Jul 23, 2018 at 2:24
  • @Tommy - Tyler is making a small generalisation here. You don't need to own or have control of the domain the image comes from to use CORS. However, you need to have control of the server the image comes from. If you do have control of that server, read up on the specific documentation (Nginx, PHP, Node.js, Java, Tomcat, Apache, Ruby-on-rails etc.) of what software is serving that image on how to enable CORS. Unfortunately, CORS is a server thing, not a browser thing (though the browser is the entity enforcing CORS) – slebetman Commented Jul 23, 2018 at 2:37
Add a comment  | 

1 Answer 1

Reset to default 13

CORS permission for images requires BOTH the server and the browser to do something.

First the browser must request CORS permission.

You do this by setting the crossOrigin on the image. Example

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

Note there are 3 valid values for crossOrigin.

  1. undefined

    this means the browser will not request CORS permissions and not check the headers. Even if the server sends the headers you will still get security errors depending on what you try to do with the image if it is from another domain. This is the default.

  2. 'use-credentials'

    this means the browser will send extra info (cookies, etc...) to the server so it can use to decide whether or not to give permission.

  3. anything else

    you can put "" or "anonymous" or "foobarmoo" or anything. If it's not undefined and it's not "use-credentials" then it's this 3rd version. It means ask for blanket CORS permission as in without any extra info.

Second the server must send the correct headers.

If you control the server you need to configure it to send the correct headers. Every server is different (apache, nginx, caddy, etc...). Each server is different and if you want to know how to configure that particular server you should look it up in the docs for that server or ask a specific question for that server.

Most servers do not send CORS headers by default. Also most 3rd party sites do not send CORS headers for images. 3 exceptions are imgur, github pages, and flickr (though sadly not stack.imgur at least as of July 2018). If you're trying to access images from random servers on the net you're out of luck except to contact their customer support and ask them to please add the headers.

In your case you're accessing an image on AWS. The server on AWS is not sending the CORS headers. Your solutions are (a) reconfigure AWS to send CORS headers if you have control of the server there (b) ask whoever controls that server to add the CORS headers (c) realize you can't do what you want without (a) or (b).

Here's a demonstration: We'll try to load your image, one image from imgur (which does set the cors headers) and another imgur but not set crossOrigin to show that BOTH setting crossOrigin AND receiving cors headers is required.

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: There's one other solution but it's arguably sketchy. You can run a proxy server that downloads the image from AWS and then sends it to your page with the CORS headers added (or sends it from the same domain as the page). I doubt that's the solution you're looking.

发布评论

评论列表(0)

  1. 暂无评论