简体   繁体   English

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

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

We are currently validating images using magic number.我们目前正在使用幻数验证图像。 Since SVG doesn't support magic number, what is the good way to validate SVG files in angularJS?由于 SVG 不支持幻数,那么在 angularJS 中验证 SVG 文件的好方法是什么?

This is how we are validating other images -这就是我们验证其他图像的方式 -

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
    };
});

Now i want to validate SVG images as well, how can we validate it without magic number?现在我也想验证 SVG 图像,我们如何在没有幻数的情况下验证它?

SVG images are XML files. SVG 图像是 XML 文件。 In a first step, you can test for the XML magic number.第一步,您可以测试 XML 幻数。 Afterwards, you could read the file content as text and parse it with DOMParser .之后,您可以将文件内容作为文本读取并使用DOMParser对其进行解析。 If an error occurs, this will tell you the file was invalid.如果发生错误,这将告诉您文件无效。

This example uses the TextDecoder API to convert the array buffer to string.此示例使用TextDecoder API 将数组缓冲区转换为字符串。 This might be a bit more restricting than doing it with a separate async FileReader.readAsText() operation.这可能比使用单独的异步FileReader.readAsText()操作更具限制性。 You should review browser compatibility to find out if this solution is good enough.您应该查看浏览器兼容性以了解此解决方案是否足够好。

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); 
          });
        }
    };

    //...
});

Obviously, this could be a memory-consuming operation if you expect to test very large files, as the complete DOM for the SVG is constructed (but not rendered).显然,如果您希望测试非常大的文件,这可能是一个消耗内存的操作,因为 SVG 的完整 DOM 已构建(但未渲染)。 My expectation would be that it is still the fastest and most reliable solution for all but some outlier use cases, like testing a large number of files in parallel.我的期望是,除了一些异常用例(例如并行测试大量文件)之外,它仍然是最快、最可靠的解决方案。

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

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