├── .scrutinizer.yml ├── LICENSE ├── README.md ├── composer.json └── src ├── Base64ImageDecoder.php ├── Base64ImageEncoder.php └── Exceptions ├── CannotEncodeToBase64.php ├── CannotReadFile.php ├── CodingFailedException.php ├── InvalidFormat.php └── NotBase64Encoding.php /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | filter: 2 | excluded_paths: [tests/*] 3 | checks: 4 | php: 5 | code_rating: true 6 | remove_extra_empty_lines: true 7 | remove_php_closing_tag: true 8 | remove_trailing_whitespace: true 9 | fix_use_statements: 10 | remove_unused: true 11 | preserve_multiple: false 12 | preserve_blanklines: true 13 | order_alphabetically: true 14 | fix_php_opening_tag: true 15 | fix_linefeed: true 16 | fix_line_ending: true 17 | fix_identation_4spaces: true 18 | fix_doc_comments: true 19 | tools: 20 | external_code_coverage: false 21 | php_analyzer: true 22 | php_code_coverage: false 23 | php_code_sniffer: 24 | config: 25 | standard: PSR2 26 | filter: 27 | paths: ['src'] 28 | php_loc: 29 | enabled: true 30 | excluded_dirs: [vendor, tests] 31 | php_cpd: 32 | enabled: true 33 | excluded_dirs: [vendor, tests] 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Alexander Melihov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Base64 Image Decoder 2 | 3 | [![Build Status](https://travis-ci.org/melihovv/base64-image-decoder.svg?branch=master)](https://travis-ci.org/melihovv/base64-image-decoder) 4 | [![styleci](https://styleci.io/repos/121083762/shield)](https://styleci.io/repos/121083762) 5 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/melihovv/base64-image-decoder/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/melihovv/base64-image-decoder/?branch=master) 6 | [![SensioLabsInsight](https://insight.sensiolabs.com/projects/1ba39d70-b4f8-4e78-9f65-dfba75f30cf5/mini.png)](https://insight.sensiolabs.com/projects/1ba39d70-b4f8-4e78-9f65-dfba75f30cf5) 7 | [![Coverage Status](https://coveralls.io/repos/github/melihovv/base64-image-decoder/badge.svg?branch=master)](https://coveralls.io/github/melihovv/base64-image-decoder?branch=master) 8 | 9 | [![Packagist](https://img.shields.io/packagist/v/melihovv/base64-image-decoder.svg)](https://packagist.org/packages/melihovv/base64-image-decoder) 10 | [![Packagist](https://poser.pugx.org/melihovv/base64-image-decoder/d/total.svg)](https://packagist.org/packages/melihovv/base64-image-decoder) 11 | [![Packagist](https://img.shields.io/packagist/l/melihovv/base64-image-decoder.svg)](https://packagist.org/packages/melihovv/base64-image-decoder) 12 | 13 | A small set of classes (decoder, encoder) to work with images as data-uris. 14 | 15 | ## Installation 16 | 17 | Install via composer 18 | ```bash 19 | composer require melihovv/base64-image-decoder 20 | ``` 21 | 22 | ## Usage 23 | 24 | ### Encoder 25 | 26 | ```php 27 | use Melihovv\Base64ImageDecoder\Base64ImageEncoder; 28 | 29 | $encoder = Base64ImageEncoder::fromFileName('/path/to/picture.jpg', $allowedFormats = ['jpeg', 'png', 'gif']); 30 | #$encoder = Base64ImageEncoder::fromBinaryData($someRawBinaryData, $allowedFormats = ['jpeg', 'png', 'gif']); 31 | #$encoder = Base64ImageEncoder::fromResource($someResource, $allowedFormats = ['jpeg', 'png', 'gif']); 32 | 33 | $encoder->getMimeType(); // image/jpeg for instance 34 | $encoder->getContent(); // base64 encoded image bytes. 35 | $encoder->getDataUri(); // a base64 data-uri to use in HTML or CSS attributes. 36 | ``` 37 | 38 | ### Decoder 39 | 40 | ```php 41 | use Melihovv\Base64ImageDecoder\Base64ImageDecoder; 42 | 43 | $dataUri = 'data:image/gif;base64,R0lGODlhLAH6AOZ/AMyokXJMK0uE...'; // image may come from http request or any other source. 44 | 45 | // We check that image is encoded properly in constructor, otherwise exception will be thrown. 46 | // You can use this info in your validation rule. 47 | $decoder = new Base64ImageDecoder($dataUri, $allowedFormats = ['jpeg', 'png', 'gif']); 48 | 49 | $decoder->getFormat(); // 'png', or 'jpeg', or 'gif', or etc. 50 | $decoder->getDecodedContent(); // base64 decoded raw image bytes. 51 | $decoder->getContent(); // base64 encoded raw image bytes. 52 | ``` 53 | 54 | ## Security 55 | 56 | If you discover any security related issues, please email amelihovv@ya.ru 57 | instead of using the issue tracker. 58 | 59 | ## Credits 60 | 61 | - [Alexander Melihov](https://github.com/melihovv/base64-image-decoder) 62 | - [All contributors](https://github.com/melihovv/base64-image-decoder/graphs/contributors) 63 | 64 | This package is bootstrapped with [melihovv/laravel-package-generator](https://github.com/melihovv/laravel-package-generator). 65 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "melihovv/base64-image-decoder", 3 | "description": "A base64 image decoder", 4 | "license": "MIT", 5 | "keywords": [ 6 | "base64", 7 | "image", 8 | "decoder" 9 | ], 10 | "type": "library", 11 | "authors": [ 12 | { 13 | "name": "Alexander Melihov", 14 | "email": "amelihovv@ya.ru" 15 | } 16 | ], 17 | "require": { 18 | "php": ">=7.0", 19 | "ext-fileinfo": "*" 20 | }, 21 | "require-dev": { 22 | "ext-gd": "*", 23 | "phpunit/phpunit": "~6.0" 24 | }, 25 | "autoload": { 26 | "psr-4": { 27 | "Melihovv\\Base64ImageDecoder\\": "src" 28 | } 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { 32 | "Melihovv\\Base64ImageDecoder\\Tests\\": "tests" 33 | } 34 | }, 35 | "scripts": { 36 | "phpunit": "phpunit" 37 | }, 38 | "config": { 39 | "preferred-install": "dist", 40 | "sort-packages": true, 41 | "optimize-autoloader": true 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/Base64ImageDecoder.php: -------------------------------------------------------------------------------- 1 | base64EncodedImage = $base64EncodedImage; 33 | $this->allowedFormats = $allowedFormats; 34 | 35 | $this->validate(); 36 | } 37 | 38 | private function validate() 39 | { 40 | $parts = explode(',', $this->base64EncodedImage); 41 | $this->format = str_replace(['data:image/', ';', 'base64'], ['', '', ''], $parts[0] ?? ''); 42 | $this->content = $parts[1] ?? ''; 43 | 44 | if (! preg_match('%^[a-zA-Z0-9/+]*={0,2}$%', $this->content)) { 45 | throw NotBase64Encoding::create(); 46 | } 47 | 48 | if (! in_array($this->format, $this->allowedFormats, true)) { 49 | throw InvalidFormat::create($this->allowedFormats, $this->format); 50 | } 51 | } 52 | 53 | public function getFormat() : string 54 | { 55 | return $this->format; 56 | } 57 | 58 | public function getContent() : string 59 | { 60 | return $this->content; 61 | } 62 | 63 | public function getDecodedContent() : string 64 | { 65 | return base64_decode($this->content); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Base64ImageEncoder.php: -------------------------------------------------------------------------------- 1 | mimeType = $mimeType; 32 | $this->base64 = $base64; 33 | } 34 | 35 | /** 36 | * @param string $mimeType 37 | * @param array $allowedFormats 38 | * @throws InvalidFormat 39 | */ 40 | private static function validate(string $mimeType, array $allowedFormats) 41 | { 42 | $format = strtr($mimeType, ['image/' => '']); 43 | 44 | if (! in_array($format, $allowedFormats, true)) { 45 | throw InvalidFormat::create($allowedFormats, $format); 46 | } 47 | } 48 | 49 | /** 50 | * @param string $content 51 | * @return string 52 | * @throws CannotEncodeToBase64 53 | */ 54 | private static function encode(string $content): string 55 | { 56 | $encoded = base64_encode($content); 57 | 58 | if (false === $encoded) { 59 | throw CannotEncodeToBase64::create(); 60 | } 61 | 62 | return $encoded; 63 | } 64 | 65 | /** 66 | * @param string $binaryData 67 | * @param array $allowedFormats 68 | * @return Base64ImageEncoder 69 | */ 70 | public static function fromBinaryData( 71 | string $binaryData, 72 | array $allowedFormats = self::DEFAULT_ALLOWED_FORMATS 73 | ) : self { 74 | $finfo = new finfo(FILEINFO_MIME_TYPE); 75 | $mimeType = $finfo->buffer($binaryData); 76 | 77 | self::validate($mimeType, $allowedFormats); 78 | 79 | return new static($mimeType, self::encode($binaryData)); 80 | } 81 | 82 | /** 83 | * @param string $fileName 84 | * @param array $allowedFormats 85 | * @return Base64ImageEncoder 86 | */ 87 | public static function fromFileName( 88 | string $fileName, 89 | array $allowedFormats = self::DEFAULT_ALLOWED_FORMATS 90 | ) : self { 91 | if (! is_readable($fileName)) { 92 | throw CannotReadFile::create($fileName); 93 | } 94 | 95 | $mimeType = mime_content_type($fileName); 96 | self::validate($mimeType, $allowedFormats); 97 | 98 | return new static($mimeType, self::encode(file_get_contents($fileName))); 99 | } 100 | 101 | /** 102 | * @param resource $handle 103 | * @param array $allowedFormats 104 | * @return Base64ImageEncoder 105 | * @throws InvalidArgumentException 106 | */ 107 | public static function fromResource($handle, array $allowedFormats = self::DEFAULT_ALLOWED_FORMATS): self 108 | { 109 | if (! is_resource($handle)) { 110 | $message = sprintf('Expected resource, got %s', is_object($handle) ? get_class($handle) : gettype($handle)); 111 | throw new InvalidArgumentException($message); 112 | } 113 | 114 | return self::fromBinaryData(stream_get_contents($handle), $allowedFormats); 115 | } 116 | 117 | public function getMimeType(): string 118 | { 119 | return $this->mimeType; 120 | } 121 | 122 | public function getContent(): string 123 | { 124 | return $this->base64; 125 | } 126 | 127 | public function getDataUri(): string 128 | { 129 | return 'data:'.$this->mimeType.';base64,'.$this->base64; 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/Exceptions/CannotEncodeToBase64.php: -------------------------------------------------------------------------------- 1 |