canvas.toDataURL() 安全错误 操作不安全
Posted
技术标签:
【中文标题】canvas.toDataURL() 安全错误 操作不安全【英文标题】:canvas.toDataURL() Security Error The operation is insecure 【发布时间】:2014-11-03 09:55:53 【问题描述】:当我在将视频上传到服务器之前尝试获取屏幕截图并将其保存为 PNG 时,我遇到了以下问题
希望你能解决我的问题...
/*Output image show view*/
$('#file_browse').change(function(e)
getVideo(this);
);
var capbtn = document.querySelector('#video_capture');
var video = document.querySelector('video');
var canvas = document.querySelector('canvas');
var context = canvas.getContext('2d');
var w, h, ratio;
video.addEventListener('loadedmetadata', function()
ratio = video.videoWidth / video.videoHeight;
w = video.videoWidth - 100;
h = parseInt(w / ratio, 10);
canvas.width = w;
canvas.height = h;
, false);
capbtn.addEventListener("click", function()
context.fillRect(0, 0, w, h);
context.drawImage(video, 0, 0, w, h);
var objImageData = canvas.toDataURL("data:image/png;");
);
function getVideo(input)
if (input.files && input.files[0])
var reader = new FileReader();
reader.onload = function (e)
var video = document.getElementsByTagName('video')[0];
var sources = video.getElementsByTagName('source');
sources[0].src = e.target.result;
video.load();
video.style.display="block";
reader.readAsDataURL(input.files[0]);
<input id="video_capture" type="submit" value="Capture" />
<video id="video_view" controls>
<source src="movie.mp4" type="video/mp4">
</video>
<canvas ></canvas>
【问题讨论】:
使用 windowURL.createObjectURL(input.files[0]) 会更流畅/更快,并且可能更慷慨。 【参考方案1】:在src
之前设置attribute
解决了我们的绘图应用程序的问题:https://www.trumpgraffitimemes.com/
useEffect(() =>
const img = new Image();
if (picdatanew.length !== 0)
img.setAttribute("crossorigin", "anonymous");
img.src = picdatanew[picID].webformatURL;
setCanvasSize(
width: picdatanew[picID].webformatWidth,
height: picdatanew[picID].webformatHeight,
);
setPicturedata(img);
setWholedata([]);
setTimeout(() =>
contextRef.current.drawImage(
img,
0,
0,
picdatanew[picID].webformatWidth,
picdatanew[picID].webformatHeight
);
var image = canvasRef.current.toDataURL("image/jpg");
setMyImage(image);
, 2000);
, [picID, picdatanew]);
【讨论】:
【参考方案2】:同样,做了一些实验得出这个结论,在 ios 上,看起来位置 .crossOrigin 参数位置应该放在 .src 之前
// Webkit will throw security error when image used on canvas and canvas.toDataUrl()
return new Promise((resolve, reject) =>
let image = new Image();
img.onload = () => resolve(image)
img.src = `$url?$Date.now()`;
img.crossOrigin = ""
)
// Webkit will not throw security error when image used on canvas and canvas.toDataUrl()
return new Promise((resolve, reject) =>
let img = new Image()
img.onload = () => resolve(img)
img.crossOrigin = ''
img.src = `$url?$Date.now()`
)
【讨论】:
【参考方案3】:就我而言,问题与不是来自我的站点的图标的存在以及选择输入的存在有关。您的视频容器可能包含相同的项目。为了解决这个问题,我不得不在截屏之前隐藏选择输入和图标,然后在截屏后再次显示它们。然后,canvas.toDataURL 完美运行,没有抛出安全错误。
截图前:
$("select[name='example']").add(".external-icon").hide();
截图后:
$("select[name='example']").add(".external-icon").show();
【讨论】:
【参考方案4】:您好,我有同样的问题,在我显示视频的系统中,我的用户必须在选择视频时创建拇指,但随后出现安全错误。
此解决方案仅在您可以修改服务器时才有效,然后您可以使用 CORS 发送视频或字体等。所以你必须编辑 httpd.conf(从你拉视频的服务器上的 Apache 配置)。
<IfModule mod_setenvif.c>
<IfModule mod_headers.c>
<FilesMatch "\.(mp4)$">
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
</FilesMatch>
</IfModule>
</IfModule>
在您的网页或应用中,在视频标签中添加:crossOrigin="Anonymous"
这是我的代码片段,之后一切都恢复正常了..
document.getElementById('video_thumb').innerhtml =
'<img src="'+data_uri+'"
crossOrigin="Anonymous">';
有了这个,canvas.toDataURL()
不要抛出错误
【讨论】:
谢谢!这也适用于视频标签:<video src=... crossOrigin="anonymous">
。这将允许在视频帧上调用toDataURL
。【参考方案5】:
这是因为Same Origin Policy。基本上,您不能使用画布访问从另一个来源/站点加载的内容的视频数据。
在画布上绘制视频数据会将 origin-clean
标志设置为 false,这会阻止您以任何方式获取图像数据。
更多信息请参见toDataURL。
【讨论】:
那怎么办..? 所以基本上这不能用于不同来源的视频?【参考方案6】:听起来像是 CORS 问题。
视频与网络服务器的来源不同。
如果您可以让视频在响应中包含“Access-Control-Allow-Origin: *”标头,并且您可以设置 video.crossorigin = "Anonymous",那么您可能可以将其取消。
我使用 Charles Web Proxy 将标题添加到我想使用的任何图像或视频中。
见https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image
另见https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes
这是一个使用图像的小提琴:http://jsfiddle.net/mcepc44p/2/
var canvas = document.getElementById("canvas").getContext("2d");
var button = document.getElementById("button");
var image = new Image();
image.crossOrigin = "anonymous"; // This enables CORS
image.onload = function (event)
try
canvas.drawImage(image, 0, 0, 200, 200);
button.download = "cat.png";
button.href = canvas.canvas.toDataURL();
catch (e)
alert(e);
;
image.src = "https://i.chzbgr.com/maxW500/1691290368/h07F7F378/"
这就是你要找的吗?
【讨论】:
这应该是公认的答案。来自 sn-p 的以下行使一切变得不同。image.crossOrigin = "anonymous"; // This enables CORS
这不应该是公认的答案,因为它不适用于 OP 要求的视频
上帝保佑你,你救了我的命;)
对于像 i.chzbgr.com 这样具有完全许可 CORS 集的网站不需要此解决方法。您可以只使用<img>
标签。 ... 但是,对于 i.imgur.com,似乎需要这种解决方法,因为服务器将 CORS 方法限制为 GET, OPTIONS
。
它不适用于我的视频。我已经设置了 CORS 标头并使用 curl -I 确认标头确实已设置。我想从视频中提取一帧并将其显示在图像中。在视频帧上调用 toDataURL() 时出现错误。以上是关于canvas.toDataURL() 安全错误 操作不安全的主要内容,如果未能解决你的问题,请参考以下文章
canvas.toDataURL() 在 IE 11 中给出“安全错误”
为啥 canvas.toDataURL() 会抛出安全异常?