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">×</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">×</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
|
1 Answer
Reset to default 13CORS 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
.
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.
'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.
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.
toBlob()
,toDataURL()
, orgetImageData()
methods; doing so will throw a security error." – Tyler Roper Commented Jul 23, 2018 at 2:19