26
Сен
2017

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

Добрый день! Есть задача: пользователь копирует картинки по интернету (ПКМ - копировать изображение), при переходе на страницу пользователь нажимает 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. Безопасность сего действа не беспокоит, так как это будет доступно ограниченному кругу лиц, на работе.

Источник: https://ru.stackoverflow.com/questions/723216/%D0%98%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5-%D0%B8%D0%B7-%D0%B1%D1%83%D1%84%D0%B5%D1%80%D0%B0-%D0%BE%D0%B1%D0%BC%D0%B5%D0%BD%D0%B0

Тебе может это понравится...

Добавить комментарий