【问题标题】:canvas.toDataURL() Security Error The operation is insecurecanvas.toDataURL() 安全错误 操作不安全
【发布时间】: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 width="300" height="300"></canvas>

【问题讨论】:

  • 使用 windowURL.createObjectURL(input.files[0]) 会更流畅/更快,并且可能更慷慨。

标签: javascript html video canvas


【解决方案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+'"  width="250"
                                height="250px" crossOrigin="Anonymous">';       
        

        有了这个,canvas.toDataURL() 不要抛出错误

        【讨论】:

        • 谢谢!这也适用于视频标签:&lt;video src=... crossOrigin="anonymous"&gt;。这将允许在视频帧上调用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 集的网站不需要此解决方法。您可以只使用&lt;img&gt; 标签。 ... 但是,对于 i.imgur.com,似乎需要这种解决方法,因为服务器将 CORS 方法限制为 GET, OPTIONS
        • 它不适用于我的视频。我已经设置了 CORS 标头并使用 curl -I 确认标头确实已设置。我想从视频中提取一帧并将其显示在图像中。在视频帧上调用 toDataURL() 时出现错误。
        猜你喜欢
        • 2017-09-15
        • 2012-12-29
        • 2012-03-09
        • 2014-03-05
        • 2015-07-18
        • 1970-01-01
        • 1970-01-01
        • 2013-06-06
        • 2018-09-07
        相关资源
        最近更新 更多