SVG将画布IE安全错误保存到DataURL

SVG tained canvas IE security error toDataURL

本文关键字:错误 保存 DataURL 安全 IE SVG      更新时间:2023-09-26

我在angular JS中有一个指令,允许将SVG导出到PNG。这在其他浏览器中运行良好,但在IE中我遇到了一个安全错误。我试过各种各样的东西,但似乎都不起作用。我在某个地方读到,如果我对它进行base64编码,那么它会起作用,但它不会。

我在画布上绘制SVG的代码是:

// Private function for drawing our images
var drawImage = function (canvas, ctx, svgContainer) {
    // Defer our promise
    var deferred = $q.defer();
    // Remove hidden layers
    removeHidden(angular.element(clone));
    // Create our data
    var clone = angular.element(svgContainer[0].cloneNode(true)),
        child = clone.children()[0];
    // Remove hidden layers
    removeHidden(angular.element(clone));
    var s = new XMLSerializer(),
        t = s.serializeToString(child),
        base64 = 'data:image/svg+xml;base64,' + window.btoa(t);
    console.log(base64);
    var img = new Image();
    // When the image has loaded
    img.onload = function () {
        // Create our dimensions
        var viewBox = child.getAttribute('viewBox').split(' ');
        console.log(viewBox);
        var dimensions = {
            width: viewBox[2],
            height: viewBox[3]
        };
        console.log(img.width);
        // Get our location
        getNextLocation(canvas.width, canvas.height, dimensions);
        // Draw our image using the context
        ctx.drawImage(img, 0, 0, dimensions.width / 2, dimensions.height, location.x, location.y, location.width, location.height);
        // Resolve our promise
        deferred.resolve(location);
    };
    // Set the URL of the image
    img.src = base64;
    // Return our promise
    return deferred.promise;
};

在此之前,我创建了一个blob,但这也导致了安全错误。我的主要代码是这一点:

// Public function to generate the image
self.generateImage = function (onSuccess) {
    // Reset our location
    location = null;
    counter = 0;
    // Get our SVG
    var target = document.getElementById(self.options.targets.containerId),
        svgContainers = angular.element(target.getElementsByClassName(self.options.targets.svgContainerClassName)),
        itemCount = svgContainers.length;
    // Get our context
    var canvas = document.getElementById('canvas'),
        ctx = canvas.getContext('2d');
    // Set our canvas height and width
    setCanvasDimensions(canvas, itemCount);
    // Create our array of promises
    var promises = [];
    // Draw our header and footer
    drawHeader(canvas, ctx);
    //// For each container
    //for (var i = 0; i < itemCount; i++) {
    //    // Get our elements
    //    var svgContainer = svgContainers[i];
    //    // Draw our image and push our promise to the array
    //    promises.push(draw(canvas, ctx, svgContainer));
    //}
    promises.push(draw(canvas, ctx, svgContainers[0]));
    // Finally add our footer to our promises array
    promises.push(drawFooter(canvas, ctx));
    // When all promises have resolve
    $q.all(promises).then(function () {
        console.log('all promises completed');
        // Get our URL as a base64 string
        var dataURL = canvas.toDataURL("image/png");
        console.log('we have the image');
        // Create our model
        var model = {
            teamName: self.options.team.name,
            sport: self.options.team.sport,
            data: dataURL
        };
        // Create our preview
        self.create(model).then(function (response) {
            console.log('saved to the database');
            // Invoke our success callback
            onSuccess(response);
        });
    })
};

如您所见,我循环浏览每个svg容器,并为每个容器绘制svg。我已经在这段代码中对此进行了评论,并只绘制了第一幅图像。canvas.toDateURL之后的console.log指令从未被调用,我得到了一个安全错误。

SVG是内联的。据我所知,这个问题可能是由于xlns声明,但删除它仍然会给我带来问题:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
   viewBox="0 0 259.5 131" enable-background="new 0 0 259.5 131" xml:space="preserve">

有人知道我该怎么解决这个问题吗?

您需要设置img.crossOrigin= 'anonymous';之前img.src=...

然而,要实现这一点,您还需要access-control-allow-origin: *设置在图像的响应标头中。

要尝试该解决方案,可以使用http://fabricjs.com/assets/printio.png'(具有正确的标头集),例如