首页 > 解决方案 > 将受污染的画布下载为 PNG

问题描述

我正在尝试制作一个按钮,当按下该按钮时,会将画布元素下载为 PNG 文件。

function downloadImage(canvas)
{
    let url = canvas.toDataURL("image/png");
    window.open(url);
}

此代码适用于未受污染的画布,但我尝试下载图像的画布已被污染,因此我无法.toDataURL()在其上运行。我见过的处理受污染的画布的许多线程都与创建画布的图像显示有关,但是有没有办法直接下载它而不创建中间图像元素?

我的网站非常简单,目前我没有在任何服务器上运行它(只是在 Google Chrome 中打开 index.html 文件)。但是,我也不想更改任何本地浏览器设置,因为我希望它在多个不同的浏览器上运行。

标签: javascripthtml

解决方案


问题是 JavaScript 旨在让您不下载任何受污染的图像。

然而,这可以被规避。您在问题中提到您正在使用文件协议;然而,评论中提到你最终会在 github 页面上使用 Web 服务器,所以也许,如果我们在这种情况下工作,我们可以完成这项工作。

首先,再次直接回答您的问题,如何下载已被操纵的受污染画布,正式浏览器的设计方式旨在防止这种情况发生,请参阅https://stackoverflow.com/a/36905778 /2016831了解更多信息。

所以现在寻找可能的解决方法。

这取决于为什么画布会被污染,是在您的代码访问它之前在上面绘制了一些东西,还是您的代码首先使其受到污染?

如果它是第二种选择,那么,如引用的答案中所述,您可以做几件事。

首先,尝试在 JavaScript 中的图像元素上添加属性 crossOrigin = "anonymous",这可能适用于某些网站。

但是对于其他人,您可以使用 nodeJS 或 PHP 或任何其他服务器端语言设置一个简单的服务器,该服务器可以漂亮地托管在任何托管平台上,该平台将对给定的图像 URL 发出 HTTP 请求,下载它并将其返回给您的客户端文件,将 access-control-allow-origin 设置为*,但是,正如答案中提到的那样,这会占用更多带宽,但如果带宽不是问题,那么你可以这样做。

或者,当然,您可以让用户简单地通过文件输入而不是 URL 上传图像,但这会限制可用性。

另一种选择,与提到的第一个“crossOrigin”解决方案有关,如果图像来自允许跨域请求的站点,您可以先使用 fetch 下载它,然后从 blob 数据中创建一个对象 URL,并设置图像的来源,然后当图像加载时,将其绘制到画布上,基本上

fetch("someURLtoAnImageOnaSiteThatAllowsCrossOriginRequests")
.then(result => result.blob())
.then(blob => {
    myImageElement.src = URL.createObjectURL(blob);
    myImageElement.onload = startDrawingImageToCanvasFunction;
})

推荐阅读