- PVSM.RU - https://www.pvsm.ru -
Практически каждый день я пользуюсь почтой Gmail, но вот недавно заметил, что если сделать скриншот экрана (www.take-a-screenshot.org/ [1]), то простым нажатием Ctrl + V этот скриншот можно скопировать прямо в текст письма Gmail. Это работает везде, но естественно кроме IE. Заинтересовавшись вопросом как это происходит нагуглил следующий пост на Stackoverflow [2]. Под сильным впечатлением от возможностей HTML5 clipboardData решил сделать простенький портал, где без всяких Desktop приложений любой юзер может загрузить скриншот [3] просто скопировав его.
Во первых надо отметить, что для того, чтобы что-то скопировать из буфера (например скриншот) в браузере должна быть поддержка Clipboard API [4]. Как можно видеть на caniuse [5] только самые последние браузеры работают с этим API. IE, к сожалению, курит в сторонке не смотря на partial support.
Для загрузки изображения из буфера (скриншота) сначала нужно определить обработчик paste события:
document.body.addEventListener("paste", function(e) {
...
});
Обработчик будет вызываться всегда, когда в рабочей области окна браузера происходит событие «Вставить», например по нажатию Ctrl + V. Далее нужно определить код, который собственно и примет файл изображения из буфера. Этот код идентичен для браузеров Chrome и Opera, но разный для FireFox, так как у последнего по каким-то соображениям безопасности закрыты методы объекта clipboardData.
// e.clipboardData.items - это и есть файлы находящиеся в буфер обмене
for (var i = 0; i < e.clipboardData.items.length; i++) {
// выбираем только картинки
if (e.clipboardData.items[i].kind == "file" && e.clipboardData.items[i].type == "image/png") {
// Получаем файл как Blob (бинарные данные)
var imageFile = e.clipboardData.items[i].getAsFile();
var fileReader = new FileReader();
fileReader.onloadend = function(e) {
// Файл прочитан в this.result его Base64 представление
loadImg(this.result);
};
// Читаем Blob как DataURL (Base64 представление бинарных данных)
fileReader.readAsDataURL(imageFile);
e.preventDefault();
break;
}
}
В FireFox у нас нет возможности прочитать файл через clipboardData. При вставке, браузер самостоятельно создает <img> тег с src в виде DataURL. Поэтому придется сделать «костыль»:
// При инициализации js, если браузера Mozilla, то добавляем скрытый, редактируемый (contenteditable) div и
// ставим на него фокус.
if ($.browser.mozilla) {
$(document.body).prepend('<div id="temp" contenteditable="true" style="height:1px;width:1px;color:#FFFFFF;"></div>');
$('#temp').focus();
}
// Определяем событие "Вставить"
document.body.addEventListener("paste", function(e) {
if ($.browser.mozilla) {
// Если Mozilla, то фокусируем на созданный ранее div
// (это нужно для того, чтобы FireFox вставил img в нужном месте)
$('#temp').focus();
// Удаляем предыдущий img (вдруг мы копируем 2, 3, ..., N раз)
$('#temp img').remove();
// У FireFox при создании img нет callback-а и единственный способ получить img - использовать небольшую паузу
setTimeout(function() {
// Вот тут FireFox точно вставил img в temp div, мы можем взять его DataURL и загрузить картинку
loadImg($('#temp img').attr('src'));
}, 1);
return true;
}
});
Загрузить картинку можно сразу на сервер, передавая через POST DataURL или например в canvas как сделано на Your screen [3]:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
...
function loadImg(dataURL) {
var imageObj = new Image();
imageObj.onload = function() {
var width = this.width, height = this.height;
canvas.width = width;
canvas.height = height;
ctx.drawImage(this, 0, 0, width, height);
};
imageObj.src = dataURL;
}
Canvas удобен тем, что перед загрузкой скриншота на сервер можно его отредактировать: подчеркнуть, нарисовать, обвести, вырезать и т.д.
На сервере должен быть POST контроллер, который бы принимал body в формате Base64 (DataURL) и декодировал его в бинарный файл изображения, например png. Контроллер может быть написан на любом языке, например Java с использованием SpringMVC:
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public @ResponseBody String save(@RequestBody String b64) {
File file = null;
FileOutputStream out = null;
try {
// Создаем Output поток
out = new FileOutputStream("/opt/files/somename.png");
// Декодируем Base64 в байты и сохраняем в поток
out.write(Base64.decodeBase64(StringUtils.replace(b64, "data:image/png;base64,", "")));
// Закрываем поток
IOUtils.closeQuietly(out);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return file.getName();
}
Для внимательных отмечу, что вот эта конструкция StringUtils.replace(b64, «data:image/png;base64,», "") нужна для нормализации передаваемого из Javascript DataURL. Дело в том, что при создании DataURL вначале ставится его тип и формат и после идет Base64 представление, например data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABVYAAAMAC…
Дополнительно можно ещё проверить размер файла, и если он превышает определенный максимум сжать в jpg.
Сервис Your screen [3] мы в компании Cackle используем каждый день в качестве быстрого и простого средства для снимка экранов наших клиентов. К сожалению, подобных решений в сети очень мало и те, что есть неудобны или работают только через Desktop:
В скором времени мы планируем перенести весь этот функционал в наш Онлайн консультант Cackle [8]. Таким образом у клиентов будет возможность сделать скриншот и передать изображение прямо через консультанта оператору. Это в некотором смысле лучшая замена Co-Browser, так как позволяет показывать весь экран (а не только браузер), снизить издержки на разработку и минимизировать ошибки.
В заключении скажу, что проект Your screen [3] совсем новый и будет развиваться дальше, поэтому жду вашей критики и пожеланий по функционалу.
Автор: cackle
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/47746
Ссылки в тексте:
[1] www.take-a-screenshot.org/: http://www.take-a-screenshot.org/
[2] Stackoverflow: http://stackoverflow.com/questions/6393280/paste-image-into-rich-text-like-gmail
[3] может загрузить скриншот: http://yourscr.com
[4] Clipboard API: http://dev.w3.org/2006/webapi/clipops
[5] caniuse: http://caniuse.com/clipboard
[6] prntscr.com: http://prntscr.com
[7] snag.gy: http://snag.gy
[8] Онлайн консультант Cackle: http://cackle.me
[9] Источник: http://habrahabr.ru/post/201190/
Нажмите здесь для печати.