快速集成移动设备摄像头到Web程序

简介

近年来,随着智能移动设备的普及,网站设计时必须同时兼顾传统的桌面浏览器(包括最常见的三大系统Windows, macOSLinux)和移动设备浏览器(一般包括iOSAndroid两大平台)。本文将分享一下如何设计一个兼顾桌面和移动浏览器的文档获取Web程序。

准备工作

下载本文中用到的是以下两个控件

Dynamic Web TWAIN 版本14.1 (.exe)

Mobile Browser Capture 版本 2.0 (.zip)

环境要求

Dynamic Web TWAIN这个SDK本身无特别的要求,而Mobile Browser Capture目前只支持.NETJava,本文中将以Java为例

  • JDK: 推荐1.8.0_172
  • Eclipse: 推荐Oxygen.3a Release (4.7.3a)
  • 64位Tomcat: 推荐Tomcat v9.0

步骤

一、创建一个Dynamic Web Application,命名为AcquireFromPCsAndMobileDevices。选择Apache Tomcat v9.0为程序的运行环境,其它都取默认值

二、从Samples入手

解压Mobile Browser Capture压缩包。解压后,拷贝 MobileBrowserCaptureSDK2.0\MobileBrowserCaptureSDK2.0\samples\javaDemo中的srcWebContent两个目录到前面生成的程序AcquireFromPCsAndMobileDevices中并覆盖冲突文件。

安装Dynamic Web TWAIN,安装后找到其安装目录, 一般位于C:\Program Files (x86)\Dynamsoft\Dynamic Web TWAIN SDK 14.1 Trial。拷贝其中的一个示例代码Samples\ScanAcquireFromPCsAndMobileDevices\WebContent

Eclipse中刷新项目确保能看到拷贝进来的文件

三、在Eclipse中添加一个server并把AcquireFromPCsAndMobileDevices加入到Server中。启动Tomcat

现在就可以在浏览器中打开刚部署的程序。链接地址为

针对移动浏览器:

http://localhost:8080/AcquireFromPCsAndMobileDevices/MobileBrowserCapture.html

针对桌面浏览器:

http://localhost:8080/AcquireFromPCsAndMobileDevices/Scan/CustomScan.html

四、先试用一下针对移动浏览器的页面

由于这个页面主要基于HTML/JSServer端代码,所以它其实可以同时在桌面浏览器和移动浏览器中使用。在桌面浏览器中显示如下

在桌面上可以直接调用摄像头(Show Video)或者加载一个本地文件(Grab Image)。我们这里加载一个文件试试

文件一载入,可以看到多出了多个功能,如删除,上传,编辑,下载等。其中编辑界面如下,可以做旋转,截取图片等操作。

在浏览器中打开这个页面,在测试阶段要求手机处于同一个WIFI内并采用本地IP访问。例如笔者的本地IP192.168.1.100,手机访问地址为

http://192.168.1.100:8080/AcquireFromPCsAndMobileDevices/MobileBrowserCapture.html

该界面专为浏览器设计,所以在手机中看起来会好很多。界面如下。默认打开页面及点击Grab Image后的显示。可见可以直接拍照,或者选择本地文件导入

导入一张图片后及上传的界面

上传后选择Redirect可以看到上传文件列表

查看server端的文件归属,默认的上传路径是用System.getProperty("user.dir")加上当前用户的ID指定的,在不同的电脑上路径可能不一样。在笔者的电脑上该路径位于

C:\Program Files\eclipse-jee-oxygen-3a-win32-x86_64\eclipse\Dynamsoft_Upload\391008ba-aa9f-4564-a285-b44a42ec7864

这个路径可以在AcquireFromPCsAndMobileDevices\WebContent\WEB-INF\web.xml中修改,如

<context-param>
    <param-name>dynamsoft_upload</param-name>
    <param-value>D:\\uploadedimages\\</param-value>
</context-param>

这样图片就会存储到以下位置

D:\uploadedimages\391008ba-aa9f-4564-a285-b44a42ec7864

五、再试用一下针对桌面浏览器的页面

打开http://localhost:8080/AcquireFromPCsAndMobileDevices/Scan/CustomScan.html。在有扫描仪的情况下,扫描一张,或者下载一个测试专用扫描仪模拟器。扫描后效果如下

六、增加一个按钮来做上传并加上JS代码及服务器端接收代码

HTML

<input type="button" value="Upload" onclick="Upload();" />

JavaScript

function Upload() {
    if (DWObject) {
        var strFullActionPagePath = location.href.substr(0, location.href.lastIndexOf('/') + 1) + 'upload.jsp';
        DWObject.HTTPUpload(strFullActionPagePath, [DWObject.CurrentImageIndexInBuffer], EnumDWT_ImageType.IT_JPG, EnumDWT_UploadDataFormat.Binary, "test.jpg", function(){}, function(errCode, errString){ console.log(errString);});
    }
}

JSP

<%@  page language="java" import="java.io.*,java.util.*,org.apache.commons.fileupload.*,org.apache.commons.fileupload.disk.*,org.apache.commons.fileupload.servlet.*"%><%!
%><%
    // Create a factory for disk-based file items
    DiskFileItemFactory factory = new DiskFileItemFactory();

    // Configure a repository (to ensure a secure temp location is used)
    ServletContext servletContext = this.getServletConfig().getServletContext();
    File repository = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
    factory.setRepository(repository);


    // Set factory constraints
    factory.setSizeThreshold(1000000000);// Sets the size threshold beyond which files are written directly to disk.

    // Create a new file upload handler
    ServletFileUpload upload = new ServletFileUpload(factory);

    // Set overall request size constraint
    upload.setSizeMax(-1);

    // Parse the request
    List<FileItem> items = upload.parseRequest(request);

    // Process the uploaded items
    Iterator<FileItem> iter = items.iterator();
    String _fields = "";
    String fileName = "";
    long sizeInBytes = 0;
    String path = application.getRealPath(request.getRequestURI());
    String dir = request.getServletContext().getInitParameter("dynamsoft_upload");
    dir = dir.replace("\\\\","/");
    String _temp_Name = dir + "files-uploaded-in-pc-browsers";
    File _fieldsTXT = new File(_temp_Name);
    if(!_fieldsTXT.exists())
    {
        boolean result = _fieldsTXT.mkdirs();
        System.out.println("File create result:"+result);
    } 

    while (iter.hasNext()) {
        FileItem item = iter.next();
        // Process a regular form field
        if (item.isFormField()) {        
        } 
        // Process a file upload
        else {
            String fieldName = item.getFieldName();
            fileName = item.getName();
            String contentType = item.getContentType();
            boolean isInMemory = item.isInMemory();
            sizeInBytes = item.getSize();
            if(fileName!=null && sizeInBytes!=0){
                File uploadedFile = new File(_temp_Name + "/" + fileName);
                if(!uploadedFile.exists())
                {
                    boolean result = uploadedFile.createNewFile();
                    System.out.println("File create result:"+result);
                }            
                try {
                    item.write(uploadedFile);
                } 
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
%>

七、增加一个环境检测的JS命名为common.js放到WebContent/js/目录用来根据环境定向跳转页面

JavaScript

var dynamsoft = dynamsoft || {};
(function () {
    var ua = navigator.userAgent.toLowerCase(),
        _platform = navigator.platform.toLowerCase(),
        _bWin = (_platform == 'win32') || (_platform == 'win64') || (_platform == 'windows'),
        _nMSIE = ua.indexOf('msie'),
        _nTrident = ua.indexOf('trident'),
        _nRV = ua.indexOf('rv:'),
        _nEdge = ua.indexOf('edge'),
        _tmp = ua.match(/version\/([\d.]+).*safari/),
        _bSafari = _tmp ? !0 : !1,
        _nSafari = _tmp ? _tmp[1] : 0,
        _nFirefox = ua.indexOf('firefox'),
        _bFirefox = (_nFirefox != -1),
        _bEdge = _bWin && !_bFirefox && (_nEdge != -1),
        _indexOfChrome = ua.indexOf('chrome'),
        _bChrome = !_bEdge && (_indexOfChrome != -1),
        _bIE = _bWin && !_bFirefox && !_bEdge && !_bChrome && (_nMSIE != -1 || _nTrident != -1 || _nRV != -1),
        _strBrowserVersion = '',
        _mainVer = 0;
    var _deviceType,
        bIsIpad = ua.match(/ipad/i) == "ipad",
        bIsIphoneOs = ua.match(/iphone os/i) == "iphone os",
        bIsMidp = ua.match(/midp/i) == "midp",
        bIsUc7 = ua.match(/rv:1.2.3.4/i) == "rv:1.2.3.4",
        bIsUc = ua.match(/ucweb/i) == "ucweb",
        bIsAndroid = ua.match(/android/i) == "android",
        bIsCE = ua.match(/windows ce/i) == "windows ce",
        bIsWM = ua.match(/windows mobile/i) == "windows mobile";
    if (bIsIpad || bIsIphoneOs || bIsMidp || bIsUc7 || bIsUc || bIsAndroid || bIsCE || bIsWM) {
        _deviceType = 'phone';
    } else {
        _deviceType = 'pc';
    }
    if (_bEdge) {
        _tmp = ua.slice(_nEdge + 5);
        _tmp = _tmp.slice(0, _tmp.indexOf(' '));
        _strBrowserVersion = _tmp;
    } else if (_bChrome) {
        _tmp = ua.slice(_indexOfChrome + 7);
        _tmp = _tmp.slice(0, _tmp.indexOf(' '));
        _strBrowserVersion = _tmp;
    } else if (_bFirefox) {    // FF
        _tmp = ua.slice(_nFirefox + 8);
        _tmp = _tmp.slice(0, _tmp.indexOf(' '));
        _strBrowserVersion = _tmp;
    } else if (_bIE) {
        if (_nMSIE != -1) {
            // 'msie'
            _tmp = ua.slice(_nMSIE + 4);
            _tmp = _tmp.slice(0, _tmp.indexOf(';'));
            _strBrowserVersion = _tmp;
        } else if (_nRV != -1) {
            // 'rv:'
            _tmp = ua.slice(_nRV + 3);
            _tmp = _tmp.slice(0, _tmp.indexOf(';'));
            _tmp = _tmp.slice(0, _tmp.indexOf(')'));
            _strBrowserVersion = _tmp;
        } else if (_nTrident != -1) {
            // 'trident'
            _tmp = ua.slice(_nTrident + 7);
            _tmp = _tmp.slice(0, _tmp.indexOf(';'));
            _strBrowserVersion = _tmp;
        }
    } else if (_bSafari) {
        if (_tmp) {
            _strBrowserVersion = _tmp[1];
        }
    }
    if (_strBrowserVersion.indexOf('.') > -1)
        _mainVer = _strBrowserVersion.slice(0, _strBrowserVersion.indexOf('.')) * 1.0;
    dynamsoft.onlineNavInfo = {
        bWin: _bWin,
        bIE: _bIE,
        bEdge: _bEdge,
        bFirefox: _bFirefox,
        bChrome: _bChrome,
        bSafari: _bSafari,
        strVersion: _strBrowserVersion,
        mainVer: _mainVer,
        deviceType: _deviceType
    };
})();
var strHREF = window.location.href;
if (dynamsoft.onlineNavInfo.deviceType == 'pc') {
    if (strHREF.indexOf('CustomScan') == -1)
        window.location.replace(strHREF.substr(0, strHREF.lastIndexOf('AcquireFromPCsAndMobileDevices') + 30) + '/Scan/CustomScan.html');
} else {
    if (strHREF.indexOf('MobileBrowserCapture') == -1)
        window.location.replace(strHREF.substr(0, strHREF.lastIndexOf('AcquireFromPCsAndMobileDevices') + 30) + '/MobileBrowserCapture.html');
}

创建一个index.jsp位于WebContent目录并加入以下代码

<%@ page session="false" pageEncoding="UTF-8" contentType="text/html; charset=UTF-8" %>
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>用扫描仪或者移动设备摄像头获取图像</title>
    </head>

    <body>
        <h1>Redirecting</h1>
    </body>
    <script type="text/javascript" src="js/common.js"></script>
</html>

MobileBrowserCapture.htmlCustomScan.html中也引用该JS,分别为

<script type="text/javascript" src="js/common.js"></script>
<script type="text/javascript" src="../js/common.js"></script>

然后如果访问http://192.168.1.100:8080/AcquireFromPCsAndMobileDevices/,则在移动设备或者PC上将跳转到对应的页面。与些同时如果访问页面与环境不对应,也将自动跳转。

这样我们就实现了同一网站访问时根据不同设备调用不同页面来实现图像的实时获取。

results matching ""

    No results matching ""