【问题标题】:How do I handle CORS with html2Canvas and AWS S3 images?如何使用 html2Canvas 和 AWS S3 图像处理 CORS?
【发布时间】:2017-07-04 22:20:45
【问题描述】:

我知道以前有人问过类似的问题,但我仍然无法解决。我有一个div,其中的图像是从 AWS s3 的存储桶中加载的,它们加载完全没问题。

现在我希望能够将特定 div 中的任何内容保存为 jpeg(比如截屏),插件 html2canvas 可以帮助解决这个问题。问题是,当我尝试实际保存它(或简单地立即显示此类屏幕截图的结果)时,我遇到了这些问题:

  • 画布被污染 => 我在插件中设置了allowTaint: true,但它会抛出这个错误,所以我禁用它并且错误消失了。我将useCORS 设置为true 以允许来自其他来源的图像。

  • CORS 政策已阻止访问图像

为了解决这个问题,我在我的 AWS S3 存储桶上设置了 CORS,但这似乎不起作用(或部分起作用)。我注意到,当插件使用它们生成 jpeg 时,这些图像的响应标头没有 CORS 元数据。然后我尝试在div 内的这些图像中设置crossOrigin="anonymous",但它会立即引发CORS 错误,这不应该发生,因为AWS 存储桶已为此设置如下:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

关于如何完成这项工作,我已经没有办法了。任何关于如何从这里开始的想法都将非常感激。

编辑:更多详细信息,我正在使用 React,并且图像 url 是从服务器检索的。这意味着,一旦我得到这个 url 数组,我就会生成:

<div>
  { urls.map(url => <img src={url} alt="some alt" />) }
</div>

如果我添加 crossOrigin="anonymous" 我会收到 CORS 错误。如果我忽略它,图像会显示,但html2canvas 插件在尝试生成“屏幕截图”时也会引发 CORS 错误。

有关 HTTP 请求的更多详细信息。所以我第一次在div 中加载图像时,这是响应标头:

Accept-Ranges:bytes
Access-Control-Allow-Methods:GET
Access-Control-Allow-Origin:*
Cache-Control:max-age=2592000
Content-Length:508208
Content-Type:image/png
Date:Thu, 16 Feb 2017 18:25:05 GMT
Last-Modified:Wed, 15 Feb 2017 19:09:44 GMT
Server:AmazonS3
Vary:Origin, Access-Control-Request-Headers, Access-Control-Request-Method 

现在,如果crossOrigin='anonymous' 并且图片不是来自缓存,则此方法有效。如果未设置 crossOrigin 属性,我会得到:

Accept-Ranges:bytes
Cache-Control:max-age=2592000
Content-Length:508208
Content-Type:image/png
Date:Thu, 16 Feb 2017 19:03:53 GMT
Last-Modified:Wed, 15 Feb 2017 19:09:44 GMT
Server:AmazonS3

或者它会在控制台上引发 CORS 错误,而不会在响应标头上显示任何元数据。我尝试在 url (?somethingsomething) 的末尾添加一个随机字符串,这样它们就永远不会从缓存中被抓取,这完全解决了这个问题。但这只是一个 hack,它现在可以工作,但它绝对不是我正在寻找的解决方案。我认为 Chrome 正在对缓存做一些事情,我很难跟踪问题的根源,除了在我的机器上很难重现这个问题,因为即使我完全使用它,它总是从缓存中检索屏幕截图新图像和禁用/清除缓存。这很混乱。

【问题讨论】:

  • Access to image has been blocked by CORS policy - 显示您用于获取图像的代码
  • 您必须直接在文档中加载带有crossOrigin 属性设置为'anonymous' 的图像,或者您可以尝试useCORS h2c 选项。 allowTaint 选项只是说你不在乎它是否会污染画布。
  • 查看编辑,我确实尝试设置 crossOrigin 属性,但没有成功,我使用 useCORS 设置为 true(忘了说抱歉)。还是没有运气。
  • 啊,你的存储桶设置有问题。已经有一段时间了,但你的 conf 对我来说似乎没问题,也许删除 Allowed header 字段,我认为没有必要。可以查this answer,挺老的,我也没有s3账号可以测试了……
  • 您能否捕获并显示失败请求的完整请求和响应标头以及整个 CORS 错误?

标签: javascript canvas amazon-s3


【解决方案1】:

查看编辑,我确实尝试将 crossOrigin 属性设置为 no 运气好,我使用 useCORS 设置为 true(忘了说抱歉)。 还是没有运气。

我修复了我在结合使用 Google Chrome、AWS S3 和多个来源时遇到的一些 cors 问题。

我发现了这个 stackoverflow 线程: Chrome + CORS + cache - requesting same file from two different origins

此错误报告的链接: https://bugs.chromium.org/p/chromium/issues/detail?id=260239

无论如何,您可以尝试这个修改后的 html2canvas 版本: https://gist.github.com/CrandellWS/6bc2078aced496004d7a045e6360f19b

使用选项:

allowTaint : false,
useCORS: true

希望对您有所帮助。

仅供参考,这会将当前时间戳添加到 cors 图像 url 以回避我在 Chrome 上遇到的缓存问题... https://gist.github.com/CrandellWS/6bc2078aced496004d7a045e6360f19b#file-html2canvas-js-L6838

这意味着重新下载这些图像会影响性能...

原帖: https://github.com/niklasvh/html2canvas/issues/1544#issuecomment-435640901

【讨论】:

  • 我看到您添加到 html2canvas 的编辑。它有助于避免在渲染后显示空白图像。我可以看到您在 img 的 src 末尾添加了 date.getTime() 作为随机数!你能解释一下为什么吗?这是否与缓存问题有关?
  • @Wowali 对我来说主要是针对 AWS Bucket 的一种不使用缓存版本并将其设置为 anonymous 的方式,这是 cors 工作所需要的......以防止污染......跨度>
  • 是的,它帮助我解决了一个域名的 CORS 问题……非常感谢
  • html2pdf 有固定的 cors 版本吗?或任何更新的解决方案请...谢谢
【解决方案2】:

我通过在 IMG 标记处添加 crossOrigin 属性解决了这个错误。因此,您的代码将如下所示(在 React js 中标记):

<Image crossOrigin="true" />

以及我在 S3 存储桶中的 CORS 配置:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
    <AllowedOrigin>http://localhost:8000</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
<CORSRule>
    <AllowedOrigin>https://testing.d1wr8lk28mi6l0.amplifyapp.com</AllowedOrigin>
    <AllowedMethod>GET</AllowedMethod>
    <AllowedMethod>HEAD</AllowedMethod>
    <AllowedMethod>PUT</AllowedMethod>
    <AllowedMethod>POST</AllowedMethod>
    <AllowedMethod>DELETE</AllowedMethod>
    <MaxAgeSeconds>3000</MaxAgeSeconds>
    <AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>

HTML2CANVAS:

 html2canvas(getWrapper, { allowTaint: true, useCORS: true, logging: true })
  .then((canvas) => {
    const imgData = canvas.toDataURL('image/png');
    console.log(imgData);
  });

【讨论】:

    【解决方案3】:

    我通过在 html2canvas 中添加 proxy:( image src ) 选项解决了这个问题。现在您的图像也包含在 pdf 中

    打字稿代码:

    download() {
            var data = document.getElementById('view-eob');
            html2canvas(data, { proxy: this.eobDetail.member.parentCompany.logo })
            .then(canvas => {
                var imgWidth = 208;
                var imgHeight = canvas.height * imgWidth / canvas.width;
                const contentDataURL = canvas.toDataURL('image/png')
                let pdf = new jsPDF('p', 'mm', 'a4');
                var position = 0;
                pdf.addImage(contentDataURL, 'PNG', 0, position, imgWidth, imgHeight)
                pdf.save(`${this.eobDetail.episode.name}-EOB.pdf`);
            });
        }
    

    HTML 代码:

    <div>
         <img [src]="this.eobDetail.member.parentCompany.logo"/>
    </div>
    <button type="button" (click)="download()"> Download</button>
    

    【讨论】:

    • 如果是多张图片怎么办?
    猜你喜欢
    • 1970-01-01
    • 2018-12-21
    • 2013-03-07
    • 2020-05-14
    • 2023-03-13
    • 2016-11-23
    • 1970-01-01
    • 2017-07-19
    • 2018-01-16
    相关资源
    最近更新 更多