На работе поставили задачу перевести нескольких сотрудников на терминальный сервер, чтобы все-все делалось на нем, в т. ч. сканирование с локального сканера. Пользователь работает в Windows. Можно было бы пробросить USB, но драйверов для Виндоус Сервера у этой модели сканера не было.
Поискал в сети по запросу Scan over RDP, нашел программы типа Scan Redirector RDP Edition, TSX Scan и т. п., за которые хотят в районе сотни-другой баксов за 1 лицензию, вроде бы даже видел за 800 баксов.
Я не люблю нелицензионный софт, поэтому решил реализовать сам:
Здесь вы видите главную страницу управления удаленным сканером. Плюс моего решения в том, что на терминальном сервере (или любом другом компьютере, с которого захотите сканировать) решительно ничего устанавливать не нужно, нужен только браузер.
Если нажать New JPG scan, увидим следующее:
А потом:
Картинку можно сохранить по правой кнопке. Нажмем New PDF scan:
Нажмем пару раз Scan PDF next page:
По клику по картинке видим ее на весь экран:
Нажмем Delete page 2:
Нажмем Make PDF:
Нажмем Browse images:
Тут можно просмотреть все, что было отсканированно ранее. Как-то так оно работает. Поддерживается любой TWAIN-совместимый сканер. Протестировано в Хроме.
Опыта разработки у меня мало, поэтому код наверняка написан в худших традициях всего. Пинайте в комментариях.
Безопасность минимальная: чтобы сканером не воспользовался посторонний, файл называется scan57578.php (имя можно изменить на другое). А в index.php напишите «Access denied».
Что нужно установить на компьютер со сканером?
Как вы уже наверно догадались, нам понадобится веб-сервер. Я использовал Denwer, который в данном случае из пушки по воробьям, но можно использовать любой другой с поддержкой PHP. При этом нужно будет соответствующим образом поправить код, так как в нем используются пути Денвера (диск Z: и т. п.).
Что нужно еще: программа CmdTwain, которая собственно сканирует из командной строки, и консольная же утилита jpeg2pfg. Устанавливаем CmdTwain, запускаем из Пуска CmdTwainSelect Source и выбираем наш сканер. Устанавливаем Денвер, соглашаемся со всем по умолчанию.
Затем на диске Z нужно найти php.ini и задать параметр max_execution_time = 130. Значение выбираем, замерив, сколько длится одно сканирование на вашем сканере. Затем Restart Denwer. Берем с рабочего стола ярлык Start Denwer и кидаем его в автозагрузку. Задаем компьютеру статический IP.
Создаем в папке Z:home папку с названием равным IP компьютера. В моем случае папка называется 10.74.0.98. В ней создаем папку www, а в ней папку, в которой будут лежать сканы. В моем случае она называется scans. Полный путь выглядит так: Z:home10.74.0.98wwwscans.
Веб-сервер настроен. Далее создайте папку Z:jpeg2pdf. В нее скопируйте jpeg2pdf.exe, который вы скачали по ссылке, которую я давал выше. А также создайте в ней файл makepdf.bat со следующим содержимым:
@echo off
z:
cd z:home10.74.0.98wwwscans%1
z:jpeg2pdfjpeg2pdf.exe -z none *.jpg -o %1.pdf
move *.pdf ..
Исправьте IP на нужный. Этот файл создает PDF из набора JPG. В качестве параметра ему передается имя папки с этим набором.
В папку Z:home10.74.0.98www поместите index57578.php (или как вы хотите его назвать) со следующим содержимым:
<?php
$ip = '10.74.0.98';
$pagename = 'scan57578.php';
$folder = 'scans';
$jpeg2pdf = 'z:\jpeg2pdf\makepdf.bat';
?>
<html>
<script>
function $_GET(key) {
var s = window.location.search;
s = s.match(new RegExp(key + '=([^&=]+)'));
return s ? s[1] : false;
}
function gettime() {
var d = new Date();
var curr_date = d.getDate();
if (curr_date < 10) curr_date = '0'+curr_date;
var curr_month = d.getMonth() + 1;
if (curr_month < 10) curr_month = '0'+curr_month;
var curr_year = d.getFullYear();
var curr_hour = d.getHours();
if (curr_hour < 10) curr_hour = '0'+curr_hour;
var curr_min = d.getMinutes();
if (curr_min < 10) curr_min = '0'+curr_min;
var curr_sec = d.getSeconds();
if (curr_sec < 10) curr_sec = '0'+curr_sec;
return curr_year+'-'+curr_month+'-'+curr_date+'-'+curr_hour+'-'+curr_min+'-'+curr_sec;
}
function jpgclick() {
document.getElementById('scanprogress').style.display = 'block';
document.getElementById('scanjpg').href='/<?=$pagename?>?scantype=jpg&time='+gettime();
}
function pdfclick() {
document.getElementById('scanprogress').style.display = 'block';
document.getElementById('scanpdf').href='/<?=$pagename?>?scantype=pdf&time='+gettime();
}
function pdfnextclick() {
document.getElementById('scanprogress').style.display = 'block';
document.getElementById('pdfnext').href='/<?=$pagename?>?scantype=pdf&time='+$_GET('time');
}
</script>
<body>
<div style="font-size: 150%">
<a id="scanpdf" href="#" style="color: #00C" onclick="pdfclick()">New PDF scan</a>
<a id="pdfnext" href="#" style="display: none; color: #00C" onclick="pdfnextclick()">Scan PDF next page</a>
<a id="makepdf" href="/<?=$pagename?>?scantype=makepdf&time=<?=$_GET['time']?>" style="color: #000; display: none">Make PDF</a><br /><br />
<a id="scanjpg" href="#" style="color: #00C" onclick="jpgclick()">New JPG scan</a><br /><br />
<a href="/<?=$folder?>/" target="_blank" style="color: #090">Browse images</a>
</div>
<br /><br />
<div id="scanprogress" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: white; display: none">
<h1 style="position: absolute; left: 20%; top: 30%">Scanning in progress. Don't close browser tab.</h1>
</div>
<?php
if($_GET['scantype']=='jpg')
{
$filename = 'Z:\home\'.$ip.'\www\'.$folder.'\'.$_GET['time'].'.jpg';
if(!is_file($filename)){
$cmd = '"C:Program FilesGssEziSoftCmdTwainCmdTwain.exe" "'.$filename.'"';
system($cmd);
}
echo ('<a href="/'.$folder.'/'.$_GET['time'].'.jpg"><img style="height: 80%" src="/'.$folder.'/'.$_GET['time'].'.jpg" alt="Picture" /></a>');
}
if($_GET['scantype']=='pdf')
{
if($_GET['delete']!='')
{
$i = -2;
$files = scandir($folder.'/'.$_GET['time']);
foreach($files as $filename)
{
$i++;
if ($filename[0] == '.') continue;
if ($_GET['delete'] == $i) system('del '.'Z:\home\'.$ip.'\www\'.$folder.'\'.$_GET['time'].'\'.$filename);
}
}
else
{
if (!is_dir($folder.'/'.$_GET['time']))
{
system('md Z:\home\'.$ip.'\www\'.$folder.'\'.$_GET['time']);
$filename = 'Z:\home\'.$ip.'\www\'.$folder.'\'.$_GET['time'].'\0001.jpg';
$cmd = '"C:Program FilesGssEziSoftCmdTwainCmdTwain.exe" "'.$filename.'"';
system($cmd);
}
else
{
$n = 1;
$files = scandir($folder.'/'.$_GET['time']);
foreach($files as $filename)
{
if ($filename[0] == '.') continue;
$t = substr($filename, 0, -4)+0;
if ($t > $n) $n = $t;
}
$n++;
$fn = str_pad($n, 4, "0", STR_PAD_LEFT).'.jpg';
$filename = 'Z:\home\'.$ip.'\www\'.$folder.'\'.$_GET['time'].'\'.$fn;
$cmd = '"C:Program FilesGssEziSoftCmdTwainCmdTwain.exe" "'.$filename.'"';
system($cmd);
}
}
$i = -2;
$files = scandir($folder.'/'.$_GET['time']);
foreach($files as $filename)
{
$i++;
if ($filename[0] == '.') continue;
echo "<table style='float: left' width='19%'><tr><td><a href='#' onclick='document.getElementById("preview").style.display="block"; document.getElementById("prepic").src="/".$folder."/".$_GET['time']."/".$filename.""'><img alt='Picture' style='width: 100%' src='/".$folder."/".$_GET['time']."/".$filename."' /></a></td></tr><tr><td align='center'><a href='/".$pagename."?scantype=pdf&time=".$_GET['time']."&delete=".$i."'>Delete page ".$i."</a><br /><br /></td></tr></table>";
}
if ($i == 0) echo '<div style="position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: white"><br /><br /><br /><center><h1><a href="/'.$pagename.'">На главную</a></h1></center></div>';
}
if($_GET['scantype']=='makepdf')
{
$cmd = $jpeg2pdf.' '.$_GET['time'];
echo '<span style="display: none">';
system($cmd);
echo "</span><h1><a href='scans/".$_GET['time'].".pdf'>Download PDF</a></h1>";
}
?>
<div id="preview" style="position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: black; color: white; display: none"><img id="prepic" style="position: relative; left: 23%; height: 100%" src="" alt="Picture" /><div style="position: absolute; top: 0; right: 0; color: #FFF"><a href="#" onclick="document.getElementById('preview').style.display='none'; return false" style="text-decoration: none; font-size: 250%; color: white; font-family: arial">X </a></div></div>
</body>
<script>
if ($_GET('scantype') == 'pdf') document.getElementById('pdfnext').style.display = 'inline';
if ($_GET('scantype') == 'pdf') document.getElementById('makepdf').style.display = 'inline';
</script>
</html>
Вверху задаются 4 параметра: IP компьютера со сканером, имя файла php, имя папки со сканами, путь к makepdf.bat.
Минусы: нельзя задать качество сканирования – сканирует всегда в 200 DPI и в цвете. Может как-то можно поменять параметры (например в реестре), но для офисных задач они подходят.
И да, я знаю, что функцию gettime() можно написать короче и красивее. Предлагайте самые красивые варианты в комментариях.
Спасибо за внимание!
Автор: akopylov