JavaScript 图片被 CORS 屏蔽
JavaScript Image blocked by CORS
下面的代码包含一个 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">×</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>
图像的 CORS 权限需要 BOTH 服务器 和 浏览器 做点什么。
首先浏览器必须请求 CORS 权限。
您可以通过在图像上设置 crossOrigin
来实现。例子
const img = new Image();
img.crossOrigin = "anonymous";
img.src = "https://somesite.com/someimage.jpg"
请注意 crossOrigin
有 3 个有效值。
未定义
这意味着浏览器不会请求 CORS 权限并且不会检查 headers。即使服务器发送了 headers,如果图像来自另一个域,您仍然会收到安全错误,具体取决于您尝试对图像执行的操作。这是默认值。
'use-credentials'
这意味着浏览器将向服务器发送额外信息(cookie 等...),以便它可以用来决定是否授予权限。
其他
您可以输入 "" 或 "anonymous" 或 "foobarmoo" 或任何内容。如果它不是 undefined 也不是 "use-credentials" 那么它就是第三个版本。这意味着在没有任何额外信息的情况下请求全面的 CORS 许可。
其次 服务器 必须发送正确的 headers。
如果您控制服务器,则需要将其配置为发送正确的 headers。每个服务器都是不同的(apache、nginx、caddy 等)。每个服务器都是不同的,如果您想知道如何配置该特定服务器,您应该在该服务器的文档中查找它或询问该服务器的特定问题。
大多数服务器默认不发送 CORS headers。此外,大多数第 3 方网站不会为图像发送 CORS headers。 3 个例外是 imgur、github 页面和 flickr(遗憾的是至少截至 2018 年 7 月还没有 stack.imgur)。如果您试图从网络上的随机服务器访问图像,那么您很不幸,只能联系他们的客户支持并要求他们添加 headers.
在您的情况下,您正在访问 AWS 上的图像。 AWS 上的服务器未发送 CORS headers。您的解决方案是 (a) reconfigure AWS to send CORS headers 如果您可以控制那里的服务器 (b) 要求控制该服务器的人添加 CORS headers (c) 意识到如果没有 ( a) 或 (b)。
这是一个演示:我们将尝试加载您的图片,一张来自 imgur 的图片(确实设置了 cors headers)和另一张未设置 crossOrigin
的图片以显示 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:还有另一种解决方案,但可以说是粗略的。您可以 运行 代理服务器从 AWS 下载图像,然后将其发送到添加了 CORS headers 的页面(或从与页面相同的域发送)。我怀疑这就是您正在寻找的解决方案。
下面的代码包含一个 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">×</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>
图像的 CORS 权限需要 BOTH 服务器 和 浏览器 做点什么。
首先浏览器必须请求 CORS 权限。
您可以通过在图像上设置 crossOrigin
来实现。例子
const img = new Image();
img.crossOrigin = "anonymous";
img.src = "https://somesite.com/someimage.jpg"
请注意 crossOrigin
有 3 个有效值。
未定义
这意味着浏览器不会请求 CORS 权限并且不会检查 headers。即使服务器发送了 headers,如果图像来自另一个域,您仍然会收到安全错误,具体取决于您尝试对图像执行的操作。这是默认值。
'use-credentials'
这意味着浏览器将向服务器发送额外信息(cookie 等...),以便它可以用来决定是否授予权限。
其他
您可以输入 "" 或 "anonymous" 或 "foobarmoo" 或任何内容。如果它不是 undefined 也不是 "use-credentials" 那么它就是第三个版本。这意味着在没有任何额外信息的情况下请求全面的 CORS 许可。
其次 服务器 必须发送正确的 headers。
如果您控制服务器,则需要将其配置为发送正确的 headers。每个服务器都是不同的(apache、nginx、caddy 等)。每个服务器都是不同的,如果您想知道如何配置该特定服务器,您应该在该服务器的文档中查找它或询问该服务器的特定问题。
大多数服务器默认不发送 CORS headers。此外,大多数第 3 方网站不会为图像发送 CORS headers。 3 个例外是 imgur、github 页面和 flickr(遗憾的是至少截至 2018 年 7 月还没有 stack.imgur)。如果您试图从网络上的随机服务器访问图像,那么您很不幸,只能联系他们的客户支持并要求他们添加 headers.
在您的情况下,您正在访问 AWS 上的图像。 AWS 上的服务器未发送 CORS headers。您的解决方案是 (a) reconfigure AWS to send CORS headers 如果您可以控制那里的服务器 (b) 要求控制该服务器的人添加 CORS headers (c) 意识到如果没有 ( a) 或 (b)。
这是一个演示:我们将尝试加载您的图片,一张来自 imgur 的图片(确实设置了 cors headers)和另一张未设置 crossOrigin
的图片以显示 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:还有另一种解决方案,但可以说是粗略的。您可以 运行 代理服务器从 AWS 下载图像,然后将其发送到添加了 CORS headers 的页面(或从与页面相同的域发送)。我怀疑这就是您正在寻找的解决方案。