Изображение из буфера обмена

313
27 сентября 2017, 11:50

Добрый день! Есть задача: пользователь копирует картинки по интернету (ПКМ - копировать изображение), при переходе на страницу пользователь нажимает CTRL+V, изображение должно загрузиться на сервер, там оно сжимается с помощью optipng или jpegoptim, в зависимости от формата изображения. Изображение после вставки на странице конвертируется из blob ссылки в base64, отправляется в таком виде на сервер, сервер его конвертирует и временно сохраняет в виде файла на сервере, после работы сервер конвертирует его обратно в base64 и отправляет ответ, и далее, у клиента выводится готовое сжатое изображение, которое он копирует таким же способом (ПКМ - копировать изображение).
Есть рабочий прототип, но в нем большая проблема. В коде используется вариант для Firefox и для Chrome. Вариант для Firefox заменять нельзя, так как только он работает на старых ОС (Windows XP), там стоит Firefox с длительной поддержкой.
Проблема в определении формата файла, пробовал разными способами, в последний раз остановился на определении формата файла по base64, но Firefox определяет все изображения как png, а Chrome вообще выводит изображения как image/plain и соответственно, невозможно подобрать, через что будет сжиматься изображение, либо через optipng, либо через jpegoptim и как в дальнейшем этот файл сохранять.

<!doctype html> 
<html> 
    <head> 
        <meta charset="UTF-8"> 
    </head> 
    <body> 
        <p>base64: <br> <textarea id="base64" placeholder="" style="width:100%"></textarea></p> 
        <img id="contenteditable" src=""> 
        <hr> 
        <img id="done" src=""> 
        <script type="text/javascript"> 
            if (!window.Clipboard) { 
                var pasteCatcher = document.createElement("div"); 
     
                pasteCatcher.setAttribute("contenteditable", ""); 
     
                pasteCatcher.style.display = "none"; 
                document.body.appendChild(pasteCatcher); 
  
                pasteCatcher.focus(); 
                document.addEventListener("click", function() { pasteCatcher.focus(); }); 
            }  
            window.addEventListener("paste", pasteHandler); 
  
            function pasteHandler(e) { 
                if (e.clipboardData) { 
                    var items = e.clipboardData.items; 
                    if (items) { 
                        for (var i = 0; i < items.length; i++) { 
                            if (items[i].type.indexOf("image") !== -1) { 
                                var blob = items[i].getAsFile(); 
                                var URLObj = window.URL || window.webkitURL; 
                                var source = URLObj.createObjectURL(blob);                 
                                createImage(source); 
                            } 
                        } 
                    } 
                    } else {       
                    setTimeout(checkInput, 1); 
                } 
            } 
  
            function checkInput() { 
                var child = pasteCatcher.childNodes[0];    
                pasteCatcher.innerHTML = "";     
                if (child) { 
                    if (child.tagName === "IMG") { 
                        createImage(child.src); 
                    } 
                } 
            } 
  
            function createImage(source) { 
                var pastedImage = new Image(); 
                pastedImage.onload = function() { 
                    document.getElementById("contenteditable").src = source; 
                } 
                pastedImage.src = source; 
 
                var xhr = new XMLHttpRequest(); 
                xhr.open('GET', pastedImage.src, true); 
                xhr.responseType = 'blob'; 
                xhr.onload = function(e) { 
                    if (this.status == 200) { 
                        var reader = new window.FileReader(); 
                        reader.readAsDataURL(this.response); 
                        reader.onloadend = function() { 
                            loadImg(reader.result); 
                        } 
                    } 
                }; 
                xhr.send(); 
            } 
             
            function loadImg(dataURL) { 
                var xmlhttp = getXmlHttp(); 
                xmlhttp.open('POST', 'compress.php', true); 
                xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); 
                xmlhttp.send("a=" + encodeURIComponent(dataURL)); 
                xmlhttp.onreadystatechange = function() { 
                    if (xmlhttp.readyState == 4) { 
                        if(xmlhttp.status == 200) { 
                            document.getElementById("base64").placeholder = xmlhttp.responseText; 
                            document.getElementById("done").src = xmlhttp.responseText; 
                        } 
                    } 
                }; 
            } 
   
            function getXmlHttp() { 
                var xmlhttp; 
                try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { 
                    try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (E) { xmlhttp = false; } 
                } 
                if (!xmlhttp && typeof XMLHttpRequest!='undefined') { xmlhttp = new XMLHttpRequest(); } 
                return xmlhttp; 
            } 
        </script> 
    </body> 
</html>

Сторона сервера:

<?php
//ini_set('display_errors','On');
//error_reporting('E_ALL');
header('Content-type: text/html; charset=windows-1251');
$base64 = $_POST["a"];
function base64_to_image($base64_string, $output_file) {
    $type0 = explode(';', $base64_string);
    $type1 = explode('/', $type0[0]);
    $GLOBALS['type'] = $type1[1];
    $data = explode(',', $base64_string);
    $source = imagecreatefromstring(base64_decode($data[1]));
    if ($GLOBALS['type'] == "png") {
        imagepng($source, $output_file.".png");
        exec("optipng -o7 img.png");
    }else if ($GLOBALS['type'] == "jpg" || $GLOBALS['type'] == "pjpeg" || $GLOBALS['type'] == "jpeg" || $GLOBALS['type'] == "plain") {
        imagejpeg($source, $output_file);
        exec("jpegoptim img");
    }else{
        echo "This file type is not supported, or the input data is corrupted! (".$GLOBALS['type'].")";
    }
    imagedestroy($source);
    return $output_file;
}
base64_to_image($base64, "img");
$ENpath = 'img';
//$ENtype = pathinfo($ENpath, PATHINFO_EXTENSION);
$ENtype = mime_content_type($ENpath);
$ENdata = file_get_contents($ENpath);
//$ENbase64 = 'data:image/' . $ENtype . ';base64,' . base64_encode($ENdata);
$ENbase64 = 'data:' . $ENtype . ';base64,' . base64_encode($ENdata);
unlink('img');
echo $ENbase64;

Просьба сильно тапками не кидаться, в JS не силен, но задачу решать как-то надо. Если необходим рабочий прототип на "посмотреть", ссылку могу предоставить.

UPD. Безопасность сего действа не беспокоит, так как это будет доступно ограниченному кругу лиц, на работе.

READ ALSO
Yii2, нужна помощь в написании метода для api

Yii2, нужна помощь в написании метода для api

Есть модели StickerPack и StickerМежду ними связь один ко многим

200
Как считать русские названия?

Как считать русские названия?

Добрый деньУ меня скрипт не может с LDAP считать русские названия

205
GET Запросы. Получение данных

GET Запросы. Получение данных

Есть запрос apibus62

234
Как быстро загрузить много данных в solr?

Как быстро загрузить много данных в solr?

Я загружаю данные через phpчерез SolrClient::addDocuments()

243