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