Building a Cross-platform Document Scanning and Management Application with Electron
Electron is a framework for building cross-platform desktop applications with HTML, JavaScript, and CSS. Since Dynamic Web TWAIN is also a cross-platform JavaScript library for document scanning and management, we can combine Electron and Dynamic Web TWAIN to implement a desktop document scanning and management application for Windows, Linux, and macOS.
Prerequisites
Install Electron and Dynamic Web TWAIN
npm install -g electron
npm install dwt
References
Electron Application for Document Scanning and Management
Step 1. Electron Quick Start
Let’s get started with electron-quick-start:
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install
npm start
Here is the basic structure of an Electron project:
app/
├── package.json
├── main.js
└── index.html
The main.js file is the entry point of Electron, defined in the package.json file:
"main": "main.js",
"scripts": {
"start": "electron main.js"
},
The index.html file is loaded in the main.js file:
mainWindow.loadURL('file://' + __dirname + '/index.htm');
// or
mainWindow.loadFile('index.html');
Although the default code works fine, if you want to make the window bigger and resizable, you can change the code:
mainWindow = new BrowserWindow({ width: 1024, height: 1024, resizable: true });
Step 2. Include Dynamic Web TWAIN JavaScript Library
To implement document scanning and document management, we just need to put some effort into the HTML5 code in index.html. There is no difference compared to building a web application.
The JavaScript library files of Dynamic Web TWAIN are located in the node_modules folder. We can include the library in the HTML file:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Document Scanner</title>
<script src="node_modules/dwt/dist/dynamsoft.webtwain.min.js"></script>
</head>
To make the SDK work, you must set the product key and specify the path of the resources:
Dynamsoft.DWT.ProductKey = 'LICENSE-KEY';
Dynamsoft.DWT.ResourcesPath = "node_modules/dwt/dist/";
Step 3. Added UI Elements
Create a select element for selecting connected document scanners, a div element as the document image container, and three buttons for scanning, loading, and saving images:
<select size="1" id="source"></select>
<div id="dwtcontrolContainer"></div>
<input type="button" value="Scan" onclick="scanImage();" />
<input type="button" value="Load" onclick="loadImage();" />
<div class="row">
<label style="font-size: x-large;">
<input type="radio" value="jpg" name="ImageType" id="imgTypejpeg" />JPEG</label>
<label style="font-size: x-large;">
<input type="radio" value="tif" name="ImageType" id="imgTypetiff" />TIFF</label>
<label style="font-size: x-large;">
<input type="radio" value="pdf" name="ImageType" id="imgTypepdf" checked="checked" />PDF</label>
<input type="button" value="Save" onclick="saveImage();" />
</div>
The radio buttons are used to select the image format for saving. The default format is PDF.
Step 4. Implement document scanning: button events
The following JavaScript code implementation includes the initialization of the Dynamic Web TWAIN object and the corresponding button events:
var dwtObject;
var selectSources = document.getElementById("source");
Dynamsoft.DWT.CreateDWTObjectEx({ "WebTwainId": "container" }, (obj) => {
dwtObject = obj;
dwtObject.Viewer.bind(document.getElementById("dwtcontrolContainer"));
dwtObject.Viewer.width = 640;
dwtObject.Viewer.height = 640;
dwtObject.Viewer.show();
onReady();
}, (errorString) => {
console.log(errorString);
});
function onReady() {
if (dwtObject) {
dwtObject.IfShowUI = false;
dwtObject.GetDevicesAsync(Dynamsoft.DWT.EnumDWT_DeviceType.TWAINSCANNER | Dynamsoft.DWT.EnumDWT_DeviceType.TWAINX64SCANNER | Dynamsoft.DWT.EnumDWT_DeviceType.ESCLSCANNER).then((sources) => {
sourceList = sources;
selectSources.options.length = 0;
for (let i = 0; i < sources.length; i++) {
let option = document.createElement("option");
option.text = sources[i].displayName;
option.value = i.toString();
selectSources.add(option);
}
});
}
}
function scanImage() {
if (!dwtObject)
return;
if (selectSources) {
var pixelTypeInputs = document.getElementsByName("PixelType");
for (var i = 0; i < pixelTypeInputs.length; i++) {
if ((pixelTypeInputs[i]).checked) {
pixelType = (pixelTypeInputs[i]).value;
break;
}
}
dwtObject.SelectDeviceAsync(sourceList[selectSources.selectedIndex]).then(() => {
return dwtObject.OpenSourceAsync()
}).then(() => {
return dwtObject.AcquireImageAsync({
IfDisableSourceAfterAcquire: true
})
}).then(() => {
if (dwtObject) {
dwtObject.CloseSource();
}
}).catch(
(e) => {
console.error(e)
}
)
} else {
alert("No Source Available!");
}
}
function loadImage() {
if (!dwtObject) return;
let onSuccess = function () { };
let onFailure = function (errorCode, errorString) { };
dwtObject.IfShowFileDialog = true;
dwtObject.LoadImageEx("", Dynamsoft.DWT.EnumDWT_ImageType.IT_ALL, onSuccess, onFailure);
}
function saveImage() {
if (dwtObject) {
if ((document.getElementById("imgTypejpeg")).checked == true) {
if (dwtObject.GetImageBitDepth(dwtObject.CurrentImageIndexInBuffer) == 1)
dwtObject.ConvertToGrayScale(dwtObject.CurrentImageIndexInBuffer);
dwtObject.SaveAsJPEG("DynamicWebTWAIN.jpg", dwtObject.CurrentImageIndexInBuffer);
}
else if ((document.getElementById("imgTypetiff")).checked == true)
dwtObject.SaveAllAsMultiPageTIFF("DynamicWebTWAIN.tiff");
else if ((document.getElementById("imgTypepdf")).checked == true)
dwtObject.SaveAllAsPDF("DynamicWebTWAIN.pdf");
}
}
Now save the changes and reload the UI. A simple desktop document scanning application is complete.

Electron Application Packaging and Distribution
To package and distribute the Electron project:
-
Install asar to pack the application into an archive file:
npm install -g asar asar pack app app.asar -
Download the Electron prebuilt package and place app.asar into the
recoursesfolder. - Double-click
electron.exeto check whether your application runs successfully. - Compress the entire folder into a zip file for distribution.
Source Code
https://github.com/yushulx/web-twain-document-scan-management/tree/main/examples/electron