How to Digitize Paper Documents in Angular Web Applications
Tags: angular, webdev, javascript, programming
Published: 2023-08-08 07:15:22

In a world that is increasingly digital, the ability to transform physical paper documents into electronic files by scanning them from a **multi-function printer (MFP)** has become a fundamental requirement for businesses of all sizes. Scanning paper documents helps create a more organized and efficient workspace. E-documents foster better collaboration between employees and departments in an organization. [Dynamic Web TWAIN](https://www.dynamsoft.com/web-twain/overview/) was born to help developers build web-based document scanning applications. Since from version 18.0, Dynamic Web TWAIN released a new feature called **Remote Scan** that allows users to wirelessly scan paper documents from a web browser on any device. In this article, we will dive into the **Remote Scan** feature by building a web application with Angular.

<video src="https://user-images.githubusercontent.com/2202306/258976267-7db0e1d0-efc2-4a54-937a-38ad7640f3d8.mp4" controls="controls" muted="muted" style="max-height:640px; min-height: 200px; max-width: 100%;"></video>

## What is Dynamic Web TWAIN Remote Scan?
Dynamic Web TWAIN is designed using the **C/S (Client/Server) model**. The SDK package comprises two parts: a client-side **JavaScript library** and a **Dynamsoft service** that includes a built-in web server and scanner access modules. The client-side library communicates with the Dynamsoft service via the **HTTP/HTTPS** protocol. 

Before version 18.0, the Dynamsoft service was only accessible from the host machine itself via `localhost` or `127.0.0.1`. When you open a web page integrated with Dynamic Web TWAIN, you must install the Dynamsoft service the first time.

![install Dynamsoft service](https://www.dynamsoft.com/codepool/img/2023/08/dynamsoft-local-scanner-service.png)

The [Remote Scan](https://www.dynamsoft.com/remote-scan/docs/introduction/) removes the restriction of accessing Dynamsoft service solely from the host machine. It exposes Dynamsoft service via a public IP address or domain name using **Bonjour**. Additionally, it provides a proxy service, built with Bonjour technology, to help you discover all Dynamsoft services running on the local network.

![Dynamic Web TWAIN remote scan](https://www.dynamsoft.com/remote-scan/docs/assets/imgs/image1.png)

## Why is Remote Scan Superior to Local Host Scan?
- You don't need to install the Dynamsoft service on every host machine. A single PC can transform all TWAIN scanners on the local network into web scanners.
- You can easily scan paper documents to **Windows**, **Linux**, **macOS**, **Android**, **iOS**, **Chrome OS**, and **Raspberry Pi** without concerns about MFP driver compatibility.


## Try Online Demo
- [Official JavaScript demo](https://demo3.dynamsoft.com/web-twain/mobile-online-camera-scanner/)
- [Angular demo](https://yushulx.me/angular-dynamic-web-twain/)

## Prerequisites
- Angular CLI: A command-line interface tool for Angular development.
  ```bash
  npm install -g @angular/cli
  ```
- [Angular Snippets for Dynamic Web TWAIN](https://marketplace.visualstudio.com/items?itemName=yushulx.dwt-code-generator): A Visual Studio Code extension that helps you quickly create an Angular application with Dynamic Web TWAIN
- [Dynamic Web TWAIN SDK](https://www.dynamsoft.com/web-twain/downloads/): The package contains the client-side JavaScript library and the Dynamsoft service.
- [Proxy Service installer](https://www.dynamsoft.com/customer/download)
    
    ![Remote Scan Proxy Service](https://www.dynamsoft.com/codepool/img/2023/08/remote-scan-proxy-service.png)
- [Trial license key for Dynamic Web TWAIN](https://www.dynamsoft.com/customer/license/trialLicense?product=dwt&source=codepool)

## Setting Up Dynamsoft Service and Proxy in Windows

**Making host machines discoverable via Bonjour**

1. Install Dynamsoft service on every host machine that has a TWAIN scanner connected.

2. Open `http://127.0.0.1:18625/` in your web browser to enable the host machine to be accessed from the local network. By default, the network access is disabled.
    
    ![Dynamsoft service](https://www.dynamsoft.com/codepool/img/2023/08/bonjour-service.png)

**Configuring the proxy service**

1. Install the proxy service package as an administrator on a host machine. The proxy service manages data transmission between the client-side library and the Dynamsoft service, functioning similarly to a router. If deployed on a powerful server, a single proxy service can serve hundreds of users simultaneously. The proxy service can also be installed on **cost-effective hardware** like the **Raspberry Pi**. You can start with one Raspberry Pi and add more devices to manage traffic as scaling needs arise.

2. Visit `http://127.0.0.1:18625/admin/proxy.html` to enable the proxy service.
    
    ![Dynamsoft proxy service](https://www.dynamsoft.com/codepool/img/2023/08/dynamsoft-proxy-service.png)

3. Open [https://www.dynamsoft.com/customer/account/certificate](https://www.dynamsoft.com/customer/account/certificate) to bind your IP address to a custom domain. The domain name is used to access the proxy service from the client-side library. The certificate is used for HTTPS communication between the client-side library and the proxy service.
    
    ![bind domain](https://www.dynamsoft.com/codepool/img/2023/08/bind-domain.png)

4. Upload the certificate and then click the **Update** button to activate the proxy service.
    
    ![proxy setup succeeded](https://www.dynamsoft.com/codepool/img/2023/08/proxy-setup-succeeded.png)

## Quick Start an Angular Application for Document Scanning
1. Install the Visual Studio extension [Angular Snippets for Dynamic Web TWAIN](https://marketplace.visualstudio.com/items?itemName=yushulx.dwt-code-generator).
2. Press `Ctrl+Shift+P` to open the command palette and then select **DWT: Create Angular Application** to create an Angular application with Dynamic Web TWAIN.
    
    ![create angular application](https://www.dynamsoft.com/codepool/img/2023/08/create-angular-application.png)
3. Request a [30-day FREE trial license](https://www.dynamsoft.com/customer/license/trialLicense?product=dwt&source=codepool) and update the license key in `src/app/dynamic-web-twain.service.ts`:

    ```typescript
    Dynamsoft.DWT.ProductKey = "LICENSE-KEY";
    ```

4. Run `npm install && ng serve --ssl` to start the application.

    ![angular application with dwt](https://www.dynamsoft.com/codepool/img/2023/08/angular-web-paper-document-scan.png)

## Create an Angular Component to Support Remote Scan
Create a new Angular component named `remote-scan`:
```bash
ng generate component remote-scan
```

Open `remote-scan.component.html` to add the following HTML code:
    
```html
<div class="row">
    <label for="BW">
        <input type="radio" value="0" name="PixelType">B&amp;W </label>
    <label for="Gray">
        <input type="radio" value="1" name="PixelType">Gray</label>
    <label for="RGB">
        <input type="radio" value="2" name="PixelType" checked="checked">Color</label>
</div>

<div>Service:
    <select (change)="onServiceChange($event)">
        <option *ngFor="let option of serviceOptions" [value]="option.value">{{ option.label }}</option>
    </select>
</div>

<div>Source: <select id="sources"></select></div>
<button (click)="acquireImage()">Scan Documents</button>

<div id="dwtcontrolContainer"></div>

<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>
</div>
<button (click)="downloadDocument()">Download Documents</button>
```

Compared to local host scanning, which only lists connected devices, an additional `<select>` element is added to allow users to choose the Dynamsoft service first. Once the service is selected, the `<select>` element for TWAIN sources will update accordingly.

Now, open `remote-scan.component.ts` to add TypeScript code.
1. Import the relevant modules:
    
    ```typescript
    import { Component, OnInit } from '@angular/core';
    import Dynamsoft from 'dwt';
    import { RemoteScanObject } from 'dwt/dist/types/RemoteScan';
    import { ServiceInfo, Device, DeviceConfiguration } from 'dwt/dist/types/WebTwain.Acquire';
    import { DynamicWebTWAINService } from '../dynamic-web-twain.service';
    ```

2. Initialize a remote scanning object with an HTTP/HTTPS address:
    
    ```typescript
    ngOnInit(): void {
      this.onReady();
    }
  
    async onReady(): Promise<void> {
      var serverurl = "document.scannerproxy.com:18602";
      if (window.location.protocol === 'https:') {
        serverurl = "document.scannerproxy.com:18604";
      }
      
      this.dwtObject = await Dynamsoft.DWT.CreateRemoteScanObjectAsync(serverurl);
      this.container = document.getElementById("dwtcontrolContainer") as HTMLElement;
      this.container.style.width = 600 + "px";
      this.container.style.height = 600 + "px";
      let ret = this.dwtObject.Viewer.bind(this.container);
      ret = this.dwtObject.Viewer.show();
    }
    ```

    You can also change the `serverurl` to `https://demo.scannerproxy.com`, a public service provided by Dynamsoft. This is intended solely for testing purposes and should not be used in production.

3. Find all services and relevant devices:
    
    ```typescript
    this.services = await this.dwtObject.getDynamsoftService();
    if (this.services) {
      if (this.services.length > 0) {
        this.serviceOptions.splice(0, 1);
      }
      for (let i = 0; i < this.services.length; i++) {
        let service = this.services[i];
        if (service.attrs.name.length > 0) {
          this.serviceOptions.push({ label: service.attrs.name, value: service.attrs.UUID });
        }
        else {
          this.serviceOptions.push({ label: service.attrs.UUID, value: service.attrs.UUID });
        }
      }
    }

    async findSources(service: ServiceInfo): Promise<void> {
      var devicetype =
        Dynamsoft.DWT.EnumDWT_DeviceType.TWAINSCANNER |
        Dynamsoft.DWT.EnumDWT_DeviceType.WIASCANNER |
        Dynamsoft.DWT.EnumDWT_DeviceType.TWAINX64SCANNER |
        Dynamsoft.DWT.EnumDWT_DeviceType.ICASCANNER |
        Dynamsoft.DWT.EnumDWT_DeviceType.SANESCANNER |
        Dynamsoft.DWT.EnumDWT_DeviceType.ESCLSCANNER |
        Dynamsoft.DWT.EnumDWT_DeviceType.WIFIDIRECTSCANNER;
  
      this.devices = await this.dwtObject!.getDevices({
        serviceInfo: service,
        deviceType: devicetype,
      });
  
      if (this.devices) {
        this.selectSources = <HTMLSelectElement>document.getElementById("sources");
        this.selectSources.options.length = 0;
        for (let i = 0; i < this.devices.length; i++) {
          this.selectSources.options.add(new Option(this.devices[i].name, i.toString()));
        }
      }
    }
    ```
4. Acquire paper documents from scanners and save them as JPEG, TIFF or PDF:
    ```typescript
    acquireImage(): void {
      if (!this.dwtObject)
        return;

      let pixelType = '2';
      var pixelTypeInputs = document.getElementsByName("PixelType");
      for (var i = 0; i < pixelTypeInputs.length; i++) {
        if ((<HTMLInputElement>pixelTypeInputs[i]).checked) {
          pixelType = (<HTMLSelectElement>pixelTypeInputs[i]).value;
          break;
        }
      }

      let type = Dynamsoft.DWT.EnumDWT_PixelType.TWPT_RGB;
      if (pixelType === '0') {
        type = Dynamsoft.DWT.EnumDWT_PixelType.TWPT_BW;
      }
      else if (pixelType === '1') {
        type = Dynamsoft.DWT.EnumDWT_PixelType.TWPT_GRAY;
      }

      let config : DeviceConfiguration = {
        PixelType: type,
      };
      this.dwtObject.acquireImage(this.devices![this.selectSources!.selectedIndex], config);
    }

    downloadDocument() {
      if (this.dwtObject && this.dwtObject.howManyImagesInBuffer > 0) {
        if ((<HTMLInputElement>document.getElementById("imgTypejpeg")).checked == true) {
          this.dwtObject.saveImages('DynamicWebTWAIN.pdf', [this.dwtObject!.currentImageIndexInBuffer], Dynamsoft.DWT.EnumDWT_ImageType.IT_JPG);
        }
        else if ((<HTMLInputElement>document.getElementById("imgTypetiff")).checked == true) {
          let indexes = Array.from({ length: this.dwtObject.howManyImagesInBuffer }, (_, index) => index);
          this.dwtObject.saveImages('DynamicWebTWAIN.pdf', indexes, Dynamsoft.DWT.EnumDWT_ImageType.IT_TIF);
        }

        else if ((<HTMLInputElement>document.getElementById("imgTypepdf")).checked == true) {
          let indexes = Array.from({ length: this.dwtObject.howManyImagesInBuffer }, (_, index) => index);
          this.dwtObject.saveImages('DynamicWebTWAIN.pdf', indexes, Dynamsoft.DWT.EnumDWT_ImageType.IT_PDF);
        }

      }
    }
    ```

## Test the Angular Application for Document Scanning

```bash
npm install 
ng server --ssl
```

![angular web paper document scan](https://www.dynamsoft.com/codepool/img/2023/08/angular-web-paper-document-remote-scan.png)

## Source Code
[https://github.com/yushulx/angular-dynamic-web-twain](https://github.com/yushulx/angular-dynamic-web-twain)