Ask AI
Table of contents

Thanks for Downloading Dynamic Web TWAIN 30-Day Trial!

Your download will start shortly. If your download does not begin, click here to retry.

Dynamic Web TWAIN with Annotations – Hello World

Dynamsoft’s Dynamic Web TWAIN (DWT) is a software development kit (SDK) designed to integrate efficient document scanning workflows into web applications. Dynamsoft Document Viewer (DDV) is a versatile web document viewer with support for document annotations. In this guide, we explain how to use DDV in place of DWT’s built-in viewer to enable annotations and provide a superior viewer experience.

In this sample, we create a headless DWT instance to scan images, and then pass the result to DDV to view, edit, annotate, etc. We then use DWT to save the result - along with any edits and annotations - to a file, or upload to the server.

Flow chart for Dynamic Web TWAIN with Annotations – Hello World

1. Add Dependencies

Use the SDK by including the packages below:

  • Dynamic Web TWAIN: provides scanning, saving, and uploading functionalities.
  • Dynamsoft Document Viewer: provides improved document viewer and annotation functionalities.

1.1 Deliver Dependencies via CDN

Deliver the SDK dependencies with either the jsDelivr or the UNPKG CDN.

  • jsDelivr

      <!--Dynamic Web TWAIN-->
      <script src="https://cdn.jsdelivr.net/npm/dwt@19.2.0/dist/dynamsoft.webtwain.min.js"></script>
      <!--Dynamsoft Document Viewer-->
      <script src="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@3.0.0/dist/ddv.js"></script>
      <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@3.0.0/dist/ddv.css">
    
  • UNPKG

      <!--Dynamic Web TWAIN-->
      <script src="https://unpkg.com/dwt@19.2.0/dist/dynamsoft.webtwain.min.js"></script>
      <!--Dynamsoft Document Viewer-->
      <script src="https://unpkg.com/dynamsoft-document-viewer@3.0.0/dist/ddv.js"></script>
      <link rel="stylesheet" href="https://unpkg.com/dynamsoft-document-viewer@3.0.0/dist/ddv.css">
    

2. Define HTML Elements

Define the following elements:

  • A container to hold the viewer

      <div id="container" style="height:580px; width:1000px"></div>
    
  • Buttons to invoke functions

      <input type="button" value="Scan" onclick="AcquireImage();" />
      <input type="button" value="Save PDF" onclick="SavePDF();" />
      <input type="button" value="Upload" onclick="Upload();" />
    

3. Initialize the SDK

3.1 Initialize Dynamsoft Document Viewer

// Dynamsoft Document Viewer
// Public trial license which is valid for 24 hours
// You can request a 30-day trial key from https://www.dynamsoft.com/customer/license/trialLicense/?product=dwtddv
Dynamsoft.DDV.Core.license = "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9";
Dynamsoft.DDV.Core.engineResourcePath = "https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@3.0.0/dist/engine";
await Dynamsoft.DDV.Core.init(); 

3.2 Create the Edit Viewer

// Create a Dynamsoft Document Viewer Edit Viewer to display and edit documents scanned with Dynamic Web TWAIN
let editViewer;
editViewer = new Dynamsoft.DDV.EditViewer({
    container: "container",
});

// Create a Dynamsoft Document Viewer document to contain and display images scanned by Dynamic Web TWAIN
let ddvDoc;
ddvDoc = Dynamsoft.DDV.documentManager.createDocument({
    name: "ddvtestDoc"
});

// Open the document
editViewer.openDocument(ddvDoc.uid);

Links to related documentation:

API Reference

3.3 Create a Viewerless Dynamic Web TWAIN Instance

Reference a CDN like jsDelivr to fetch most resources using Dynamsoft.DWT.ResourcesPath. Notably these resources exclude DWT Service installers, which exceed the jsDelivr CDN per-file size limit. You have a few options to set this path with Dynamsoft.DWT.ServiceInstallerLocation:

  1. Install the DWT SDK, extract the DWT service installers (under path like C:\Program Files (x86)\Dynamsoft\Dynamic Web TWAIN SDK 19.2\Resources\dist), then self-host the DWT Service installers with Dynamsoft.DWT.ServiceInstallerLocation = "https://example.com/DWT/Resources/dist".
  2. Use a different CDN with a higher per-file size limit by referencing the location with Dynamsoft.DWT.ServiceInstallerLocation = "https://unpkg.com/dwt@19.2.0/dist/dist".
// Create Dynamic Web TWAIN object
// Public trial license which is valid for 24 hours
// You can request a 30-day trial key from https://www.dynamsoft.com/customer/license/trialLicense/?product=dwtddv
Dynamsoft.DWT.ProductKey = "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9";
Dynamsoft.DWT.UseDefaultViewer = false;
Dynamsoft.DWT.ResourcesPath = "https://cdn.jsdelivr.net/npm/dwt@19.2.0/dist";
// Do not forget to set your installer path
Dynamsoft.DWT.ServiceInstallerLocation = "YOUR_INSTALLER_PATH_HERE";

let DWObject;
// Create a Dynamic Web TWAIN instance without the built-in viewer
Dynamsoft.DWT.CreateDWTObjectEx({
        WebTwainId: "dwtId",
    },function (object) {
        DWObject = object;
    }, function (error) {
        console.log(error);
    }
);

API Reference

4. Use SDK Features

4.1 Add Simple Scanning Functionality

Use the Dynamic Web TWAIN instance for scanning. Upon scan completion, import the scanned data into DDV for viewing, editing, and annotating.

4.1.1 Register the OnPostTransferAsync Event

//Register the OnPostTransferAsync event in the success callback function of CreateDWTObjectEx.
Dynamsoft.DWT.CreateDWTObjectEx({
        WebTwainId: "dwtId",
    },
    function (object) {
        DWObject = object;
        // Call Dynamsoft_OnPostTransferAsync upon completion of every individual page scan
        DWObject.RegisterEvent("OnPostTransferAsync", Dynamsoft_OnPostTransferAsync);
    },
    function (error) {
        console.log(error);
    }
);

// Import scanned page into Dynamsoft Document Viewer to display
function Dynamsoft_OnPostTransferAsync(outputInfo){
    if(DWObject) {
        let index = DWObject.ImageIDToIndex(outputInfo.imageId);
        DWObject.ConvertToBlob(
            [index], 
            Dynamsoft.DWT.EnumDWT_ImageType.IT_PNG, 
            function(blob){
                ddvDoc.loadSource(blob);
            }, 
            function(ec,es){
                console.log(es);
            }
        );
    }
}

API Reference

4.1.2 Use Dynamic Web TWAIN to Scan from Document Scanners

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

API Reference

4.2 Add PDF Saving to Local Functionality

Use saveToPdf() from DDV to convert the scanned document to a PDF Blob, then use saveBlob from DWT to export the document to local as a PDF.

const pdfSettings = {
   saveAnnotation: "annotation"  
};
function SavePDF(){
    editViewer.currentDocument.saveToPdf(pdfSettings).then(function(blob){
        DWObject.IfShowFileDialog = true;
        DWObject.saveBlob("WebTWAINImage.pdf", blob).then(function () {
            console.log("OK");
        }).catch(function (err) {
            console.log(err);
        });
    });
}

API Reference

4.3 Add Server Upload Functionality

Use the saveToPdf() API from DDV to convert the scanned document to a PDF Blob, then use the httpUploadBlob() API from DWT to upload the document to the server as a PDF.

// Can be discarded if already defined previously
const pdfSettings = {
   saveAnnotation: "annotation"  
};

function Upload(){
    editViewer.currentDocument.saveToPdf(pdfSettings).then(function(blob){
        let fileName = "WebTWAINImage.pdf";
        DWObject.httpUploadBlob(
            "https://demo.dynamsoft.com/sample-uploads/",
            blob,
            fileName
        ).then(function () {
            console.log("Upload successful.");
        }).catch(function (err) {
            console.log(err);
        });
    });
}

Links to related documentation:

API Reference

Review the Complete Code

<!DOCTYPE html>
<html>
<head>
    <title>HelloWorld</title>
    <script src=" https://cdn.jsdelivr.net/npm/dwt@19.2.0/dist/dynamsoft.webtwain.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@3.0.0/dist/ddv.js"></script>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@3.0.0/dist/ddv.css">
</head>
<body>
    <button onclick="AcquireImage();">Scan</button>
    <button onclick="SavePDF();">Save PDF</button>
    <button onclick="Upload();">Upload</button>
    <div id="container" style="height:580px; width: 1000px;"></div>
</body>
<script type="text/javascript">
let DWObject, editViewer, ddvDoc;
(async function(){
    // Dynamsoft Document Viewer
    // Public trial license which is valid for 24 hours
    // You can request a 30-day trial key from https://www.dynamsoft.com/customer/license/trialLicense/?product=dwtddv
    let license = "DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9";
    Dynamsoft.DDV.Core.license = license;
    Dynamsoft.DDV.Core.engineResourcePath = "https://cdn.jsdelivr.net/npm/dynamsoft-document-viewer@3.0.0/dist/engine";
    await Dynamsoft.DDV.Core.init(); 

    // Create a Dynamsoft Document Viewer Edit Viewer to display and edit documents scanned with Dynamic Web TWAIN
    editViewer = new Dynamsoft.DDV.EditViewer({
        container: "container"
    });

    // Create a Dynamsoft Document Viewer document to contain and display images scanned by Dynamic Web TWAIN
    ddvDoc = Dynamsoft.DDV.documentManager.createDocument({
        name: "ddvtestDoc"
    });

    // Open the document
    editViewer.openDocument(ddvDoc.uid);

    // Create Dynamic Web TWAIN object
    Dynamsoft.DWT.ProductKey = license;
    Dynamsoft.DWT.UseDefaultViewer = false;
    Dynamsoft.DWT.ResourcesPath = "https://cdn.jsdelivr.net/npm/dwt@19.2.0/dist";
    // Do not forget to set your installer path
    Dynamsoft.DWT.ServiceInstallerLocation = "YOUR_INSTALLER_PATH_HERE";

    // Create a Dynamic Web TWAIN instance without the built-in viewer
    Dynamsoft.DWT.CreateDWTObjectEx({
        WebTwainId: "dwtId",
    },function (object) {
        DWObject = object;
        // Call Dynamsoft_OnPostTransferAsync upon completion of every individual page scan
        DWObject.RegisterEvent("OnPostTransferAsync", Dynamsoft_OnPostTransferAsync);
    }, function (error) {
        console.log(error);
    });
})();

// Import scanned page into Dynamsoft Document Viewer to display
function Dynamsoft_OnPostTransferAsync(outputInfo){
    if(DWObject) {
        let index = DWObject.ImageIDToIndex(outputInfo.imageId);
        DWObject.ConvertToBlob(
            [index], 
            Dynamsoft.DWT.EnumDWT_ImageType.IT_PNG, 
            function(blob){
                ddvDoc.loadSource(blob);
            },
            function(ec,es){
                console.log(es);
            }
        );
    }
}


// Scan with Dynamic Web TWAIN
function AcquireImage() {
    if (DWObject) {
        DWObject.SelectSourceAsync().then(function () {
            return DWObject.AcquireImageAsync({ 
                IfCloseSourceAfterAcquire: true 
            });
        }).catch(function (exp) {
            alert(exp.message);
        });
    }
}

const pdfSettings = {
   saveAnnotation: "annotation"  
};

function SavePDF(){
    editViewer.currentDocument.saveToPdf(pdfSettings).then(function(blob){
        DWObject.IfShowFileDialog = true;
        DWObject.saveBlob("WebTWAINImage.pdf", blob).then(function () {
            console.log("OK");
        }).catch(function (err) {
            console.log(err);
        });
    });
}

function Upload(){
    editViewer.currentDocument.saveToPdf(pdfSettings).then(function(blob){
        let fileName = "WebTWAINImage.pdf";
        DWObject.httpUploadBlob(
            "https://demo.dynamsoft.com/sample-uploads/",
            blob,
            fileName
        ).then(function () {
            console.log("Upload successful.");
        }).catch(function (err) {
            console.log(err);
        });
    });
}

</script>
</html>

Run the Web Application

Flow chart for Dynamic Web TWAIN with Annotations – Hello World

Further Reading

Last modified date: Sep 20, 2024

Is this page helpful?

YesYes NoNo

In this article: