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