How to Upload Scanned Documents in Node.js with Dynamic Web TWAIN

In the digital era, managing documents efficiently is crucial for businesses and individuals alike. With the rise of web technologies, scanning and uploading documents through web applications has become a sought-after feature. This article introduces a practical way to implement document scanning and uploading in a web application using Dynamic Web TWAIN SDK and Node.js. Whether you’re developing an application for document management, archival, or processing, integrating these technologies can streamline your document handling processes.

What you’ll build: A Node.js Express web application that scans documents from a TWAIN-compatible scanner and uploads them to a server using the Dynamic Web TWAIN SDK.

Key Takeaways

  • Dynamic Web TWAIN provides browser-based document scanning via TWAIN, WIA, and SANE protocols with a JavaScript API.
  • The Node.js Express server handles uploaded scanned images using the Formidable module for multipart form parsing.
  • The client-side SDK can load, scan, and upload document images with three core API calls: LoadImageEx, AcquireImageAsync, and HTTPUploadThroughPost.
  • This approach works for document management, archival, and processing workflows that require scanner-to-server image transfer.

Common Developer Questions

  • How do I upload scanned documents to a Node.js server?
  • How do I integrate Dynamic Web TWAIN with Express for document scanning?
  • What is the best way to scan and upload documents from a browser using JavaScript?

What Is Dynamic Web TWAIN?

Dynamic Web TWAIN is a powerful browser-based document scanning SDK that enables developers to quickly implement document scanning, uploading, editing, and processing functionalities within web applications. It supports a wide range of scanners and provides a seamless user experience, making it a popular choice for businesses and developers looking to enhance their web applications with document imaging capabilities.

Prerequisites

  • Node.js installed on your development machine.
  • Dynamic Web TWAIN SDK. There are three ways to obtain it:
    • Download the SDK package from the official website. The package includes the JavaScript library, documentation, sample code, and a 30-day free trial license.
    • Install from npm:

      npm install dwt
      
    • Use the CDN link:

      <script src="https://unpkg.com/dwt/dist/dynamsoft.webtwain.min.js"></script>
      
  • Get a 30-day free trial license for Dynamic Web TWAIN.

Step 1: Set Up the Node.js Express Server

Install Express and Formidable. Express is a widely used web application framework for Node.js, and Formidable is a module for parsing form data, particularly useful for handling file uploads.

```bash
npm install formidable express
```

Create a file named server.js to initialize the web server using Express.

```js
var formidable = require('formidable');
var util = require('util');
var express = require('express');
var fs = require('fs');
var app = express();
app.use(express.static(__dirname));
app.use(express.static(__dirname + '/Resources')); // load static resources
app.use(function (req, res, next) {
	res.header("Access-Control-Allow-Origin", "*");
	res.header("Access-Control-Allow-Methods", "PUT, POST, GET, DELETE, OPTIONS");
	res.header("Access-Control-Allow-Headers", "X-Requested-With, content-type");
	res.header("Access-Control-Allow-Credentials", true);
	next();
});
``` Incorporate a route that manages file uploads. Utilize Formidable to parse the uploaded file information and store the file in a designated directory.

```js
app.post('/upload', function (req, res) {
	var form = new formidable.IncomingForm();
	form.parse(req, function (err, fields, files) {

		fs.readdir(__dirname + "/UploadedImages/", function (err, readfiles) {
			if (err) {
				fs.mkdir(__dirname + "/UploadedImages/", function (err) {
				});
			}

			fs.readFile(files.RemoteFile.path, function (err, data) {
				// save file from temp dir to new dir
				var newPath = __dirname + "/UploadedImages/" + files.RemoteFile.name;
				fs.writeFile(newPath, data, function (err) {
					if (err) throw err;
					console.log('file saved');
					res.end();
				});
			});
		});
	});
})
```

Assign a port number for the server to listen on.

```js
var server = app.listen(2024, function () {
	var host = server.address().address;
	var port = server.address().port;
	console.log('listening at http://%s:%s', host, port);
})
```

Step 2: Create the Client-Side Document Scanning Page

With the server ready, create a web page to scan and upload documents using Dynamic Web TWAIN.

Construct a web page featuring a content container and three buttons. This content container will display the scanned images, while the buttons will facilitate loading, scanning, and uploading document images.

```html
<html>
    <head>
        <script src="https://unpkg.com/dwt/dist/dynamsoft.webtwain.min.js"> </script>
    </head>
    <body>
        <table>
    		<tr>
    			<td>
    				<div id="dwtcontrolContainer"></div>
    			</td>
    		</tr>
    		<tr>
    			<td>
    				<input type="button" value="Load Image" onclick="LoadImages();" />
    				<input type="button" value="Scan Image" onclick="AcquireImage();" />
    				<input id="btnUpload" type="button" value="Upload Image" onclick="btnUpload_onclick()">
    			</td>
    		</tr>
    	</table>
    </body>
</html>
```

Insert a snippet of code to initialize Dynamic Web TWAIN, ensuring the ResourcesPath property is directed to the location of the Dynamic Web TWAIN resources.

```js
var DWObject;

window.onload = function () {
    Dynamsoft.DWT.AutoLoad = false;
    Dynamsoft.DWT.UseLocalService = true;
    Dynamsoft.DWT.Containers = [{ ContainerId: 'dwtcontrolContainer', Width: '640px', Height: '640px' }];
    Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', Dynamsoft_OnReady);
    // https://www.dynamsoft.com/customer/license/trialLicense/?product=dcv&package=cross-platform
    Dynamsoft.DWT.ProductKey = 'LICENSE-KEY';
    Dynamsoft.DWT.ResourcesPath = 'https://unpkg.com/dwt/dist/';

    Dynamsoft.DWT.Load();
};

function Dynamsoft_OnReady() {
    DWObject = Dynamsoft.DWT.GetWebTwain('dwtcontrolContainer');
}
```

Implement additional lines of code to define the actions for each button.

- Load images:
    
    ```js
    function LoadImages() {
		if (DWObject) {
			DWObject.LoadImageEx('', 5,
				function () {
				},
				function (errorCode, errorString) {
					alert('Load Image:' + errorString);
				}
			);
		}
	}
    ```    
    
- Scan images:

    ```js
    function AcquireImage() {
        if (DWObject) {
            DWObject.SelectSourceAsync().then(function () {
                return DWObject.AcquireImageAsync({
                    IfCloseSourceAfterAcquire: true
                });
            }).catch(function (exp) {
                alert(exp.message);
            });
        }
    }
    ```    

- Upload images:

    ```js
    function btnUpload_onclick() {
		var strHTTPServer = location.hostname;
		DWObject.IfSSL = Dynamsoft.Lib.detect.ssl;
		var _strPort = location.port == "" ? 80 : location.port;
		if (Dynamsoft.Lib.detect.ssl == true)
			_strPort = location.port == "" ? 443 : location.port;
		DWObject.HTTPPort = _strPort;
		var CurrentPathName = unescape(location.pathname);
		var CurrentPath = CurrentPathName.substring(0, CurrentPathName.lastIndexOf("/") + 1);
		var strActionPage = CurrentPath + "upload";
		var sFun = function () {
			alert('success to upload!');
		}, fFun = function () {
			alert('fail to upload!');
		};
		var Digital = new Date();
		var uploadfilename = Digital.getMilliseconds();
		DWObject.HTTPUploadThroughPost(
			strHTTPServer,
			DWObject.CurrentImageIndexInBuffer,
			strActionPage,
			uploadfilename + ".jpg",
			sFun, fFun
		);
	}
    ```    

Save this web page as index.html and launch the server.

```bash
node server.js
```

Navigate to http://localhost:2024 in your web browser to begin scanning and uploading documents.

Scan and upload documents with Dynamic Web TWAIN and Node.js

Common Issues and Edge Cases

  • Dynamsoft Service not detected: Dynamic Web TWAIN requires the Dynamsoft Service to be running on the client machine for scanner access. If scanning fails, verify the service is installed and running. Download it from the Dynamsoft Service page.
  • Upload fails with large files: The Formidable default upload size limit may reject large multi-page scans. Increase the limit by setting form.maxFileSize in your server route (e.g., form.maxFileSize = 200 * 1024 * 1024 for 200 MB).
  • CORS errors when running client and server on different ports: The Express CORS middleware shown above allows all origins (*). In production, restrict Access-Control-Allow-Origin to your application’s domain for security.

Source Code

https://github.com/yushulx/web-twain-document-scan-management/tree/main/examples/node_upload