【问题标题】:How to handle downloading external images using html2canvas?如何使用 html2canvas 处理下载外部图像?
【发布时间】:2022-01-28 11:51:07
【问题描述】:

我有一个包含几本书封面的页面和一个下载所有封面的按钮。

图书封面采用字符串格式,是一个 Google 图书网址。我是这样填充的:

<section ref="capture" id="my-node">
  <figure v-for="book in books" :key="book.id">
    <img :src="book.thumbnail" :alt="`Book ${book.title}`" />
  </figure>
  <button type="button" @click="download">html2canvas</button>
</section>

要下载书籍封面,我正在调用以下函数:

download() {
  html2canvas(this.$refs["capture"], { allowTaint: true })
    .then((canvas) => {
      let link = document.createElement("a");
      link.download = "Livrero.png";
      link.href = canvas.toDataURL("image/png");
      link.click();
    })
},

Books 是一个包含 thumbnail 属性的对象,其值如下:https://books.google.com/books/content?id=_i6bDeoCQzsC&amp;printsec=frontcover&amp;img=1&amp;zoom=1&amp;edge=curl&amp;source=gbs_api

让我更困惑的是,如果我使用类似于这样的值:https://images-na.ssl-images-amazon.com/images/I/41xShlnTZTL._SX218_BO1,204,203,200_QL40_FMwebp_.jpg 一切都会正常工作,但不幸的是,该项目目前不允许这样做。


以前我在html2canvas 中使用属性useCORS: true,但是它返回了CORS 策略错误。因此,当我删除它时,我不再出现此错误并开始收到以下错误:

DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement':
Tainted canvases may not be exported.

有人建议我使用http://html2canvas.hertzen.com/proxy/来完成任务,但是因为我使用的是Vue.js,所以我不知道如何应用。

【问题讨论】:

  • 好吧,我假设您使用的服务(愚蠢地)确认 URL 是基于文件扩展名的图像,在这种情况下,如果他们没有很好的输入验证,您可以只需将 &amp;.jpg&amp;.png 添加到图片 URL 的末尾即可。
  • @Arnon 现在我想知道您为什么使用不专门从事该任务的库。你为什么不直接关注this answer
  • 它适用于亚马逊,因为您引用的是存储在他们服务器上的文件的绝对路径,因此后缀为 .jpg(这就是 AWS 的工作方式,这是他们的设计选择)。另一方面,谷歌利用查询字符串来动态加载图像。不是疯狂的传统,但无论 Google 做什么都会成为传统,对吧?
  • @gre_gor 你怎么知道 OP 是这样使用 html2canvas 的?如果是这样,那将是一种浪费......(可能只是将图像加载到画布上)
  • @Arnon 那么您能否在代码中添加一个您收到的错误示例?

标签: javascript cors html2canvas


【解决方案1】:

这是浏览器内容政策的问题。没有简单的解决方案。

浏览器不允许您使用来自不同来源的内容(图像),而这些内容并未明确允许。

对于useCORS: true,预计服务器(带有远程资源)会使用适当的access-control-allow-origin 标头进行响应。您的亚马逊链接可以,这就是它起作用的原因。

使用allowTaint: true,它接受图像,但拒绝让您对生成的画布图像执行任何操作,因为它现在被视为tainted

由于您无法让第 3 方服务器发送适当的 CORS 标头,因此您必须运行自己的 CORS 代理。

要运行the official documentation 中提到的html2canvas-proxy,您需要安装它

npm install html2canvas-proxy --save

创建一个启动 JavaScript 文件

var proxy = require('html2canvas-proxy');
var express = require('express');
const port = 8000;

var app = express();
app.use('/', proxy());
app.listen(port, () => {
  console.log(`html2canvas-proxy listening on port ${port}`)
})

然后在html2canvas 中使用proxy 选项

html2canvas(this.$refs["capture"], {
    proxy: "http://localhost:8000",
})
.then((canvas) => {
  // ...
})

但是对于生产来说,这个简单的代理也不是很好,因为它允许任何人使用它作为 CORS 代理,如果您还没有运行 Express Node.js 服务器,您可能不需要单独的服务器。

【讨论】:

  • 我看不出 Vue 与这里有什么关系。 Vue 是一个前端框架。你在后端运行什么并不重要。
  • 我之前没有运行后端,现在我运行了,并且正在运行。我想知道是否没有我不必运行后端的解决方案。这在生产中会变得很烦人。
猜你喜欢
  • 1970-01-01
  • 2017-07-04
  • 1970-01-01
  • 1970-01-01
  • 2018-10-25
  • 2017-05-01
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多