【问题标题】:CORS issue with canvas only when image is preloaded仅在预加载图像时,画布出现 CORS 问题
【发布时间】:2020-02-19 17:50:40
【问题描述】:

我的问题仅在加载的图像在其他地方预加载时出现。例如,当我在某处使用带有src 属性的<img>-tag 时。

看看这段代码:

 <canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;" ></canvas>
 
 <img src="https://local-spaces.fra1.digitaloceanspaces.com/test.jpg" width="50"/>
 
 <button onclick="show()">Load Canvas Picture</button>
 
 <script>
function show() {
  	const c = document.getElementById("myCanvas");
    const ctx = c.getContext("2d");

    const img = new Image();
    img.setAttribute('crossOrigin', 'anonymous');


    img.onload = function(){
      ctx.drawImage(img,0,0, 300, 150);
    };
		
    img.src = "https://local-spaces.fra1.digitaloceanspaces.com/test.jpg"
   
}
</script>

注意:如果您在画布中正确看到图像,请缓存+硬重新加载您的浏览器以查看错误。

如果您单击按钮并打开控制台,您会看到出现 CORS 错误:

在以下位置访问图像 'https://local-spaces.fra1.digitaloceanspaces.com/test.jpg' 来自 原点“null”已被 CORS 策略阻止:否 请求中存在“Access-Control-Allow-Origin”标头 资源。

现在让我们看下一个例子,看看它在没有预加载图像的情况下工作:https://jsfiddle.net/akzxp9vs/

注意:要使这个示例正常运行,删除缓存 + 硬重新加载浏览器非常重要。

只有这样您才能看到正确的标头响应正在回馈。

任何想法我能做什么?

图片位于名为 Spaces 的 S3 数字海洋云上。图像本身设置为公开,CORS 设置设置为:

【问题讨论】:

  • CORS 设置显然不起作用。尝试使用curl -i https://local-spaces.fra1.digitaloceanspaces.com/test.jpg 或 Postman 等。响应中没有 Access-Control-Allow-Origin 标头。
  • @sideshowbarker — curl -H "Origin: http://example.com/" -i https://local-spaces.fra1.digitaloceanspaces.com/test.jpg
  • @sideshowbarker 奇怪的是,在第二个示例中响应标头设置正确...
  • @RolandStarke 这也困扰着我!我曾经删除 crossOrigin,但是当我尝试获取图像的 blob 文件时,出现错误:DOMException: Failed to execute 'toBlob' on 'HTMLCanvasElement': Tainted canvases may not be exported.
  • Shadrix 是的,正如@Quentin 指出的那样,我测试不正确。服务器希望看到一个 Origin 标头,如果没有看到,它不会将 Access-Control-Allow-Origin 标头添加到响应中。如果请求包含 Origin 标头,则响应将具有预期的 Access-Control-Allow-Origin 标头。无论如何,请参阅@Quentin 的回答

标签: javascript amazon-s3 cors digital-ocean


【解决方案1】:

浏览器需要知道在发出 HTTP 请求时检查 CORS 权限(即包含 Origin 标头等)。

当您创建一个新的Image 对象时,它会使用来自&lt;img&gt; 元素的缓存数据。

crossorigin 属性添加到现有&lt;img&gt; 元素或完全删除该&lt;img&gt; 元素。

【讨论】:

  • 嗯,你是说我需要在整个页面中将跨域添加到我的所有 &lt;img&gt;tags 吗?
  • @Shadrix — 仅用于画布的那些。
  • 我提出了一个新问题。我以为 CORS 的乐趣已经结束,但事实并非如此。或许你可以看看there as well
【解决方案2】:

我找到了解决问题的更好方法。 @Quentin 的解决方案基本上是正确的,但它只是不切实际。我尝试更新所有&lt;img&gt;-tag,但是在我的页面中,我有几十个包也在使用&lt;img&gt;-tag。

例如传单。它类似于 Google 地图,但具有开放式街道地图。您只是无法控制在自定义图标中设置 crossorigin 等属性。

所以必须有另一种解决方案。使用它感觉很糟糕,但它确实有效。

const src = new URL(imgUrl);
src.searchParams.append('cors', Date.now());
return src.href;

此代码会在您的 URL 中附加一个查询参数,并强制 Chrome 重新加载图像而不进行缓存。

【讨论】:

    猜你喜欢
    • 2017-08-12
    • 1970-01-01
    • 2011-02-24
    • 2017-04-11
    • 1970-01-01
    • 1970-01-01
    • 2013-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多