首页 > 解决方案 > Amazon S3 奇怪的 CORS 行为:请求的资源上不存在“Access-Control-Allow-Origin”标头

问题描述

我在亚马逊 S3 上存储图像。

我将这个 CORS 配置用于我的存储桶:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration>
 <CORSRule>
    <AllowedOrigin>https://www.monteurzimmer-1a.de</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedHeader>*</AllowedHeader>
 </CORSRule>
</CORSConfiguration>

我也有桶规则:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket/*"
        }
    ]
}

问题是:

我的图像通常都是可见的,没有任何问题,在我添加脚本以根据其 EXIF 数据旋转图像后出现错误。

现在,如果您第一次访问该页面(图像旋转的页面),您仍然可以看到图像,但未应用旋转,并且我在控制台中看到每个图像的错误:... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

但是,如果您重新加载页面一次,那么错误就会消失并应用旋转。您可以使用隐身模式重现该问题。

以隐身模式访问此页面。可以看到图像但旋转会出错,错误出现在控制台中。按 F5,错误消失,应用旋转。

我认为这与缓存有关,但旋转脚本不在 S3 上。

这就是我应用旋转的方式:

<img class="display-none" id="room_image_{{ loop.index }}"
onload="rotate_image(this)" alt="Zimmer Bild" 
src="https://s3.eu-central-1.amazonaws.com/my-bucket/userimages/{{ image.path }}">

这是JS部分:

function adjust_to_container($img, deg) {
    //console.log($img);
    //var parentHeight = $img.parent().height();
    var parentHeight = $img.parentElement.clientHeight;

    //console.log(parentHeight);
    if (deg == 90 || deg == 270) {
        $img.style.maxWidth = parentHeight + "px";
        //$img.css("max-width", parentHeight + "px");
    }
}

function rotate_image($img) {
    EXIF.getData($img, function() {
        console.log('Exif=', EXIF.getTag($img, "Orientation"));

        switch(parseInt(EXIF.getTag($img, "Orientation"))) {
            case 2:
                //$img.addClass('flip'); 
                $img.classList.add("flip");
                adjust_to_container(this, 180);
                break;
            case 3:
                //$img.addClass('rotate-180');
                $img.classList.add("rotate-180");
                adjust_to_container(this, 180);
                break;
            case 4:
                //$img.addClass('flip-and-rotate-180'); 
                $img.classList.add("flip-and-rotate-180");
                adjust_to_container(this, 180);
                break;
            case 5:
                //$img.addClass('flip-and-rotate-270'); 
                $img.classList.add("flip-and-rotate-270");
                adjust_to_container(this, 270);
                break;
            case 6:
                //$img.addClass('rotate-90'); 
                $img.classList.add("rotate-90");
                adjust_to_container(this, 90);
                break;
            case 7:
                //$img.addClass('flip-and-rotate-90'); 
                $img.classList.add("flip-and-rotate-90");
                adjust_to_container(this, 90);
                break;
            case 8:
                //$img.addClass('rotate-270'); 
                $img.classList.add("rotate-270");
                adjust_to_container(this, 270);
                break;
        }
    });
}

exif.js此脚本在 HTML 中加载,<HEAD>因为它们必须在加载图像之前存在。

任何想法为什么会触发 CORS 问题?

编辑

我认为这与 EXIF.js 有关。它用于XMLHttpRequest处理图像。这是我使用的 exit.js

编辑

这个问题似乎只发生在 chrome 浏览器上,这意味着 CORS 配置没问题?

标签: javascriptimageamazon-web-servicesamazon-s3cors

解决方案


我添加crossorigin="anonymous"了图像标签,似乎错误消失了。

<img class="display-none" id="room_image_{{ loop.index }}"
onload="rotate_image(this)" crossorigin="anonymous" alt="Zimmer Bild" 
src="https://s3.eu-central-1.amazonaws.com/my-bucket/userimages/{{ image.path }}">

可以在此处接受的答案中找到一个小的解释。


推荐阅读