How to Scan Documents in a Nuxt.js App

Nuxt is a free and open-source framework with an intuitive and extendable way to create type-safe, performant and production-grade full-stack web applications and websites with Vue.js.

In this article, we are going to build a document scanner using Nuxt.js and Dynamic Web TWAIN. It can scan documents via scanners using protocols like TWAIN, WIA, ESCL, SANE, and ICA.

Demo screenshot:

screenshot

Prerequisites

Get your trial key.

New Project

Create a new Nuxt.js project named document-scanner:

npx nuxi@latest init document-scanner

Install Dependencies

  1. Install Dynamic Web TWAIN.

    npm install dwt
    
  2. Copy the resources of Dynamic Web TWAIN to the public folder.

    1. Install ncp.

      npm install ncp --save-dev
      
    2. Modify package.json to add the following scripts:

      "build": "ncp node_modules/dwt/dist public/assets/dwt-resources && nuxt build",
      "dev": "ncp node_modules/dwt/dist public/assets/dwt-resources && nuxt dev",
      

      Remember to create the assets/dwt-resources folder beforehand.

Create a Vue Component to Scan and View the Documents

Next, let’s create a document scanner component under components/DocumentScanner.vue.

In the template, add a div as the container of the viewer of Dynamic Web TWAIN.

<template>
  <div ref='viewer' id='dwtcontrolContainer'></div>
</template>

When the component is mounted, load Dynamic Web TWAIN and register the OnWebTwainReady event. When Web TWAIN is ready, a document viewer will appear in the container. The Web TWAIN object for further actions is emitted using the onWebTWAINReady event.

<script setup lang='ts'>
import { onMounted, ref, watch } from 'vue';
import Dynamsoft from 'dwt';
import { WebTwain } from 'dwt/dist/types/WebTwain';

const emit = defineEmits(['onWebTWAINReady']);
const viewer = ref(null);
const ContainerId = 'dwtcontrolContainer';
let DWObject:WebTwain|undefined;

const initDWT = () => {
  Dynamsoft.DWT.RegisterEvent('OnWebTwainReady', () => {
    DWObject = Dynamsoft.DWT.GetWebTwain(ContainerId);
    emit('onWebTWAINReady',DWObject);
  });

  Dynamsoft.DWT.ResourcesPath = 'assets/dwt-resources';
  Dynamsoft.DWT.Containers = [{
      WebTwainId: 'dwtObject',
      ContainerId: ContainerId
  }];
  Dynamsoft.DWT.Load();
}

onMounted(async () => {
  initDWT();
});
</script>

In addition, we can make the viewer occupy the entire container with the following steps:

  1. Set the style for the container.

    <style lang="css" scoped>
    #dwtcontrolContainer {
      width: 100%;
      height: 100%;
    }
    </style>
    
  2. Modify the viewer’s size.

    DWObject.Viewer.width = "100%";
    DWObject.Viewer.height = "100%";
    

Use the Document Scanner Component in the App

Switch to app.vue. Let’s use the scanner component in the app.

  1. Import the scanner component. Since the SDK has to modify the DOM, we need to wrap the scanner with ClientOnly.

    <template>
      <div>
        <h2>Document Scanner</h2>
        <div id="viewer">
          <ClientOnly>
            <DocumentScanner @onWebTWAINReady="onWebTWAINReady"></DocumentScanner>
          </ClientOnly>
        </div>
      </div>
    </template>
    <script setup lang="ts">
    import { WebTwain } from 'dwt/dist/types/WebTwain';
    let DWTObject:WebTwain|undefined;
    const onWebTWAINReady = (dwt:WebTwain) => {
      DWTObject = dwt;
    };
    </script>
    <style lang="css" scoped>
    #viewer {
      width: 320px;
      height: 320px;
    }
    </style>
    
  2. Add a button to trigger scanning.

    <template>
      <button @click="scan">Scan</button>
    </template>
    <script setup lang="ts">
    const scan = ()=> {
      if (DWTObject) {
        DWTObject.SelectSourceAsync()
          .then(function () {
            return DWTObject!.AcquireImageAsync({
              IfCloseSourceAfterAcquire: true,
            });
          })
          .catch(function (exp) {
            alert(exp.message);
          });
      }
    }
    </script>
    
  3. Add a button to save the scanned document pages as a PDF file.

    <template>
      <button @click="save">Save</button>
    </template>
    <script setup lang="ts">
    const save = ()=> {
      if (DWTObject) {
        DWTObject.SaveAllAsPDF("Scanned.pdf",
        function(){
          console.log("success")
        },
        function(errorCode:number,errorString:string){
          console.log(errorString)
        });
      }
    }
    </script>
    

All right, we’ve now finished the document scanner with Nuxt.js. You can check out the online demo to have a try.

Source Code

https://github.com/tony-xlh/NuxtJS-Document-Scanner