繁体   English   中英

我们如何在不使用 AngularJS 中的幻数的情况下验证 SVG 图像

[英]How can we validate SVG Image without using magic number in AngularJS

我们目前正在使用幻数验证图像。 由于 SVG 不支持幻数,那么在 angularJS 中验证 SVG 文件的好方法是什么?

这就是我们验证其他图像的方式 -

angular.module('fileMimeTypeServiceModule', [])
.constant('fileMimeTypeServiceConstants', {
    VALID_IMAGE_MIME_TYPE_CODES: ['FFD8FFDB', 'FFD8FFE0', 'FFD8FFE1', '474946383761', '424D', '49492A00', '4D4D002A', '89504E470D0A1A0A']
})
.factory('seFileReader', function() {
    var read = function(file, config) {
        var fileReader = new FileReader();

        config = config || {};
        fileReader.onloadend = config.onLoadEnd;
        fileReader.onerror = config.onError;

        fileReader.readAsArrayBuffer(file);
        return fileReader;
    };

    return {
        read: read
    };
})
.factory('fileMimeTypeService', function(fileMimeTypeServiceConstants, seFileReader, $q) {
    var _validateMimeTypeFromFile = function(loadedFile) {
        var fileAsBytes = (new Uint8Array(loadedFile)).subarray(0, 8);
        var header = fileAsBytes.reduce(function(header, byte) {
            var byteAsStr = byte.toString(16);
            if (byteAsStr.length === 1) {
                byteAsStr = '0' + byteAsStr;
            }
            header += byteAsStr;
            return header;
        }, '');

        return fileMimeTypeServiceConstants.VALID_IMAGE_MIME_TYPE_CODES.some(function(mimeTypeCode) {
            return header.toLowerCase().indexOf(mimeTypeCode.toLowerCase()) === 0; // validating here
        });
    };

    var isFileMimeTypeValid = function(file) {
        var deferred = $q.defer();
        seFileReader.read(file, {
            onLoadEnd: function(e) {
                if (_validateMimeTypeFromFile(e.target.result)) {
                    deferred.resolve();
                } else {
                    deferred.reject();
                }
            },
            onError: function() {
                deferred.reject();
            }
        });
        return deferred.promise;
    };

    return {
        isFileMimeTypeValid: isFileMimeTypeValid
    };
});

现在我也想验证 SVG 图像,我们如何在没有幻数的情况下验证它?

SVG 图像是 XML 文件。 第一步,您可以测试 XML 幻数。 之后,您可以将文件内容作为文本读取并使用DOMParser对其进行解析。 如果发生错误,这将告诉您文件无效。

此示例使用TextDecoder API 将数组缓冲区转换为字符串。 这可能比使用单独的异步FileReader.readAsText()操作更具限制性。 您应该查看浏览器兼容性以了解此解决方案是否足够好。

angular.module('fileMimeTypeServiceModule', [])
.constant('fileMimeTypeServiceConstants', {
    VALID_IMAGE_MIME_TYPE_CODES: [ 'ffd8ffdb', 'ffd8ffe0', 'ffd8ffe1', '474946383761', '424d', '49492a00', '4d4d002a', '89504e470d0a1a0a' ],
    XML_MIME_TYPE_CODE: '3c3f786d6c'
})
.factory('seFileReader', function() {/*...*/})
.factory('fileMimeTypeService', function(fileMimeTypeServiceConstants, seFileReader, $q) {
    var _validateMimeTypeFromFile = function(loadedFile) {
        var u8arr = new Uint8Array(loadedFile);
        var fileAsBytes = (u8arr).subarray(0, 8);
        var header = fileAsBytes.reduce(function(header, byte) {
            var byteAsStr = byte.toString(16);
            if (byteAsStr.length === 1) {
                byteAsStr = '0' + byteAsStr;
            }
            header += byteAsStr;
            return header;
        }, '');

        if (header.toLowerCase().startsWith(fileMimeTypeServiceConstants.XML_MIME_TYPE_CODE) {
            try {
                var fileContentAsString = new TextDecoder('utf-8').decode(u8arr);
                var parser = new DOMParser();
                parser.parseFromString(fileContentAsString, 'image/svg+xml');
                return true;
            } catch (e) {
                return false;
            }
        } else {
          return fileMimeTypeServiceConstants.VALID_IMAGE_MIME_TYPE_CODES.some(function(mimeTypeCode) {
              return header.toLowerCase().startsWith(mimeTypeCode); 
          });
        }
    };

    //...
});

显然,如果您希望测试非常大的文件,这可能是一个消耗内存的操作,因为 SVG 的完整 DOM 已构建(但未渲染)。 我的期望是,除了一些异常用例(例如并行测试大量文件)之外,它仍然是最快、最可靠的解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM