如何使用 html2Canvas 和 AWS S3 图像处理 CORS?
Posted
技术标签:
【中文标题】如何使用 html2Canvas 和 AWS S3 图像处理 CORS?【英文标题】:How do I handle CORS with html2Canvas and AWS S3 images? 【发布时间】: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 />)
</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 错误?
【参考方案1】:
查看编辑,我确实尝试将 crossOrigin 属性设置为 no 运气好,我使用 useCORS 设置为 true(忘了说抱歉)。 还是没有运气。
我修复了我在结合使用 Google Chrome、AWS S3 和多个来源时遇到的一些 cors 问题。
我发现了这个 *** 线程: 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 工作所需要的......以防止污染......跨度>
我在github.com/niklasvh/html2canvas/issues/…github.com/niklasvh/html2canvas/issues/…项目的githubs问题列表上发布了这个
是的,它帮助我解决了一个域名的 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>
【讨论】:
如果是多张图片怎么办?以上是关于如何使用 html2Canvas 和 AWS S3 图像处理 CORS?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 S3 用作静态网页和 EC2 作为 REST API 一起使用? (AWS)
如何使用 AWS 在 Docker Cloud 中设置链接到 S3 的卷?
如何使用 AWS AppSync 将文件上传到 AWS S3