从 chrome 使用 HTTPS 从 S3 下载图像时出现 CORS 错误,但在 Firefox 中也能正常工作

Mri*_*Raj 8 google-chrome amazon-s3 cors imagedownload angular8

我正在尝试从 S3 下载 .jpg 和 .pdf 图像,其具有以下设置

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedHeader>*</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
Run Code Online (Sandbox Code Playgroud)

按照类似于(How do I download a file with Angular2)的方法,在 Firefox 中一切正常。在 Chrome 中,PDF 下载工作正常,但当我尝试下载图像时,总是收到 GET 请求的典型 CORS 错误。

 downloadFile(url, type, fileName) {
    this.http.getFile(url, { responseType: 'blob' }).
      subscribe(data => this.downloadFileComplete(data, type, fileName));
  }

  downloadFileComplete(data: any, type: string, fileName: string) {
    let fileType = (type === 'IMAGE') ? 'image/jpeg' : 'application/pdf';
    var blob = new Blob([data], { type: fileType.toString() });
    if (type === 'IMAGE') {
      saveAs(blob, fileName + ".jpg");
    }
    else {
      saveAs(blob, fileName + ".pdf");
    }
  }
Run Code Online (Sandbox Code Playgroud)

访问 XMLHttpRequest at ' https://xxxxxxxxxxxxxx.s3.ap-south-1.amazonaws.com/certifications/3c35754f-b3c4-42f2-953a-8af52b5ed19bf2bc5370-9481-492a-8174-dfcc63d5a9bd.jpg ' from origin ' http: //localhost:4200 ' 已被 CORS 策略阻止:请求的资源上不存在 'Access-Control-Allow-Origin' 标头。

经过一些研究,我发现了这个解决方法(https://zyst.io/how-to-fix-aws-s3-chrome-and-safari-cors-on-images),他们建议对 S3 使用 HTTP URL 。当我尝试此操作时,图像下载再次开始工作。有人可以向我解释一下吗

  1. 为什么在 Chrome 中,获取图像的 GET 调用会引发图像的 CORS 错误,而不会引发 PDF 的 CORS 错误?

  2. 这个问题有合适的解决方案吗?我的网站在 HTTPS 上运行,因此基于 HTTP 的解决方案并不好。

小智 2

我尝试了多种解决方案,直到能够针对此问题开发以下解决方法。

创建一个 lambda 函数以将 s3 图像作为 base64 提供服务

我编写了这个 lambda 函数来获取 S3 对象并将其作为 base64 返回

const AWS = require("aws-sdk");
const s3 = new AWS.S3();

const imageConversor = async (event, context, callback) => {
  const { imageUrl } = event.queryStringParameters;
  const params = { Bucket: "your-bucket-name", Key: imageUrl };
  const response = await s3.getObject(params).promise();
  const fileContent = response.Body.toString("base64");
  callback(null, {
    statusCode: 200,
    body: JSON.stringify({
      image: fileContent,
    }),
    headers: {
      "Access-Control-Allow-Origin": "*",
    },
  });
};
Run Code Online (Sandbox Code Playgroud)

获取 Base64 图像,然后将其转换为 blob,以便您可以下载它

// this base64toBlob function was written by Jeremy at /sf/ask/1137203721/

const base64toBlob = function (b64Data, contentType, sliceSize) {
  contentType = contentType || "";
  sliceSize = sliceSize || 512;
  var byteCharacters = window.atob(b64Data);
  var byteArrays = [];

  for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
    var slice = byteCharacters.slice(offset, offset + sliceSize);

    var byteNumbers = new Array(slice.length);
    for (var i = 0; i < slice.length; i++) {
      byteNumbers[i] = slice.charCodeAt(i);
    }

    var byteArray = new Uint8Array(byteNumbers);

    byteArrays.push(byteArray);
  }
  var blob = new Blob(byteArrays, { type: contentType });
  return blob;
};

const onDownloadClick = async (url) => {
  const data = await axios.get("/imageConversor?imageUrl=" + url.replace("https://your-bucket-name.s3.amazonaws.com/", ""));
  const blobImage = base64toBlob(url);
  saveAs(blobImage || url, `fileName.png`);
}
Run Code Online (Sandbox Code Playgroud)