Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

How to Scan Tiff and PDF from the Web

27 Nov 2009 1  
There are some things, such as scanning documents, that cannot be done with just browser technologies like HTML and Javascript. For this reason we have developed a simple to use ActiveX Twain control which requires only basic Javascript knowledge to use effectively.

This article is in the Product Showcase section for our sponsors at CodeProject. These articles are intended to provide you with information on products and services that we consider useful and of value to developers.

More and more companies are moving to web based solutions, and can you blame them? The web provides easy integration with other systems as well as a single point from which all end users can be upgraded. The one issue with building web applications is that there are some things, such as scanning documents, that cannot be done with just browser technologies like HTML and Javascript and you have to use things like ActiveX.

ActiveX is a difficult beast and the requirements for running in any particular version of Internet Explorer are a moving target. For this reason we have developed a simple to use ActiveX Twain control which requires only basic Javascript knowledge to use effectively. You need only paste an object tag on to your site, wire up a few events, and run a couple of simple commands. In this article, you will do the following tasks

Let’s get started.

Installing and Licensing DotTwain

Before we can begin you must first download and install the Atalasoft DotTwain Toolkit. After the installation completes, our Activation Wizard will start, and you should request a 30-day evaluation of DotTwain. The following images demonstrate each step of the process. Please note that while the version numbers may have changed the steps will remain the same.

  1. Download and install the latest version of our DotTwain Toolkit
  2. When the installer completes, the Toolkit Activation Wizard with automatically start. Click Next to begin.

    image001.jpg

  3. Select “Request 30-day Evaluation” and click Next.

    image002.jpg

  4. Ensure “DotTwain” is selected under Toolkits to Evaluate. You can safely select other options here if you wish to explore other aspects of our toolkit as well. Once you have DotTwain selected, put your Atalasoft.com account name and password in and click Next.

    image003.jpg

  5. Finally, Click Finish to exit the Activation Wizard.

    image004.jpg

Put the Scanning ActiveX Control on a Page and Initialize it

Now that you have DotTwain installed and licensed you can move on and being building your Twain ActiveX Scanning Solution. To do this first it is necessary to create a Web Site project and place the necessary cab file in that location. To do this:

  1. Create a new web site in an empty directory in Visual Studio.

    image005.jpg

  2. Copy Atalasoft.DotTwain.Controls.cab, which can be found in your “\bin\2.0\x86” DotTwain installation subdirectory, to your web site directory.

    image006.jpg

  3. Add the DotTwain ActiveX Control Object Tag to your html.
    <object id="ScanningControl" 
               name="ScanningControl" 
            classid="clsid:7D7102FE-6517-441c-AE7A-3DA4085B1E73"
            codebase="Atalasoft.DotTwain.Controls.cab#version=1,0,0,0" 
            height="0" 
            width="0">
    </object>
  4. Finally, add a call to the Control’s Initialize() function to the onload property of your page. This will ensure that the control is initialized each time the page is loaded.
    <body onload="return
    document.ScanningControl.Initialize();">

At this point we have the basics in place but not anything we can do real work with. Before we can continue it will first be necessary to create a way to save images on the server once they are scanned.

Create a Service to Save Your Scanned Images

Next, it is necessary to create a small service which can save your files as they are uploaded.

  1. Create Images Subfolder inside of your Web Site directory. This will be where scanned files will be stored.
  2. Create a new Web Form called FileStorage.aspx. This Web Form will act as an image upload service to handle the upload and later download of scanned images.

    image007.jpg

  3. Finally, add the following code to your FileStorage.cs code behind. It both saves incoming files to the images folder which you previously made and retrieves images from said folder when they are requested with the GetFile parameter.
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            string fileStoragePath = 
                Path.Combine(Request.PhysicalApplicationPath, "Images");
     
            //If the GetFile parameter is present return the requested file.
            string requestedFilename = Request.Params["GetFile"];
            if (requestedFilename != null)
            {
                string safeFilename = Path.GetFileName(requestedFilename);
                string fullFilePath = Path.Combine(fileStoragePath,
                                        safeFilename);
     
                if (File.Exists(fullFilePath))
                {
                    Response.WriteFile(fullFilePath);
                }
            }
     
            //If the request contains files, save them.
            if (Request.Files.Count > 0)
            {
                foreach (String field in Request.Files.AllKeys)
                {
                    HttpPostedFile file = Request.Files[field];
                    string safeFilename = Path.GetFileName(file.FileName);
                    string fullFilePath = 
                            Path.Combine(fileStoragePath, safeFilename);
     
                    file.SaveAs(fullFilePath);
                }
            }
        }
        catch (Exception ex)
        {
            Debug.Write(ex.ToString());
        }
    }

Now that we have a way to save and retrieve images in place, we can move on to wiring up our ActiveX control.

Scan and Upload by calling the control with Javascript

Next, it is necessary to wire up the control with Javascript so that it can be used. Our interface is based on the Javascript event model which allows you simultaneously scan and upload images with only a small amount of effort.

  1. Add a Scan Button and Javascript.

    First add an input button to your Form which will call Scan() when clicked.

    <input type="button" value="Scan" onclick="Scan()" />

    Then we must define our Scan() function. Here we create a new batch process for scanning and simply pass it to the ScanBatch method of the control. Notice that the scanningDevice variable will currently always be null as we have not yet built a way to select a scanner.

    <script language="javascript" type="text/javascript">
    scanningDevice = null;
     
    function Scan() {
      if (scanningDevice) {
        var batch = document.ScanningControl.CreateNewBatch(scanningDevice);
        document.ScanningControl.BatchScan(batch);
      }
    }
    </script>
  2. Add a Device Selection Combo Box and Javascript.

    For this step we will first need to create a select tag to contain our scanner options. This will be a dropdown box which will contain all Twain devices found on the system.

    Device: <select id="ScannerList" 
             onchange="return SelectedScannerChanged();"></select>

    We must then define a series of simple Javascript functions to manage our new dropdown box:

    • GetSelectedScanner() retrieves the text name of the currently selected scanner in the dropdown box.
    • SelectedScannerChanged() is designed to be called when the selected scanner is changed so that the selectedDevice variable will always contain a queryable representation of the currently selected scanning device.
    • FillScannerSelect() takes an array of available scanners and adds each of them to the ‘ScannerList’ select box. When it is finished it calls SelectedScannerChanged() to ensure the state of the scanningDevice variable is correct.
    <script language="javascript" type="text/javascript">
     
    function GetSelectedScanner() {
      var formatSelect = document.getElementById("ScannerList");
      return formatSelect.options[formatSelect.selectedIndex].value;
    }
     
    function SelectedScannerChanged() {
      var scannerName = GetSelectedScanner();
      scanningDevice = document.ScanningControl.GetDevice(scannerName);
    }
     
    function FillScannerSelect(scannerArray) {
      var scannerSelect = document.getElementById("ScannerList");
      scannerSelect.length = 0;
      if (scannerArray.length > 0) {
          for (var i = 0; i < scannerArray.length; i++) {
              scannerSelect.add(new Option(scannerArray[i], scannerArray[i]));
          }
      }
      scannerSelect.selectedIndex = 0;
      SelectedScannerChanged();
    }
     
    </script>
  3. Set up Control Initialization

    We now have everything necessary to build our list of scanners in place but you will notice that it currently never initially gets called. The appropriate place to do this is in the ControlInitializationComplete event. When this event is called you will know that Twain is ready to use and that licensing completed successfully. Before this point it is not safe to call any of the control’s functions other than Initialize().

    <script for="ScanningControl" event="ControlInitializationComplete(args)" 
        language="jscript" type="text/jscript">
      if (args.TwainIsAvailable == true) {
        var scannerArray = document.ScanningControl.GetAvailableDevices();
        FillScannerSelect(scannerArray);
      } 
    </script>

    It’s also a good idea to add a stub for ControlInitializationStarting as this is where licensing will take place once you have the full version of DotTwain.

    <script for="ScanningControl" event="ControlInitializationStarting(args)" 
        language="jscript" type="text/jscript">
      //Note: To deploy it is necessary to set the url to your license here.
      //args.LicenseUrl = "http://hostname/Atalasoft.DotTwain.lic";
    </script>
  4. Set up File Transfer and Display

    Now that our control is actively working we must add the uploading functionality. First let’s add a div to put our freshly scanned images into.

    <div id="ScannedImages"></div>

    Next we must define a series of functions to make it easier to manage adding and removing images from this div:

    <script language="javascript" type="text/javascript">
    function GetFileStorageUrl() {    
      var href = window.location.href;
      var baseUrl = href.substring(0, href.lastIndexOf("/"));
      var urlUploadLocation = baseUrl + "/FileStorage.aspx";
      return urlUploadLocation;
    }
     
    function GetFileDownloadUrl(filename) {    
      var fileStorageUrl = GetFileStorageUrl();
      var fullUrl = fileStorageUrl + "?GetFile=" + filename;
      return fullUrl;
    }
     
    function AddImageToScannedImages(url) {
         var uploadedImagesDiv = document.getElementById("ScannedImages");
         var aTag = document.createElement('A');
         aTag.setAttribute("href", url);
         aTag.innerText = "Image<br />";
         uploadedImagesDiv.appendChild(aTag);
    }
    </script>

    We must then add hooks for the TransferStarting and TransferComplete events. At the time TransferStarting is called you must specify the url the scanned image will uploaded to. If args.TransferArgs.Uri is not specified the Control will throw an error.

    <script for="ScanningControl" event="TransferStarting(args)" language="jscript" 
        type="text/jscript">
        args.TransferArgs.Uri = GetFileStorageUrl();
    </script>

    When TransferComplete is called we know the image has been successfully transferred and so we can safely add it to our ‘ScannedImages’ div.

    <script for="ScanningControl" event="TransferComplete(args)" language="jscript" 
        type="text/jscript">
        var imageUrl = GetFileDownloadUrl(args.TransferArgs.Filename);
        AddImageToScannedImages(imageUrl);
    </script>
  5. Record Errors

    Finally, to record any errors which might happen it is necessary to hook in to the Control’s Error event.

    <script for="ScanningControl" event="Error(args)" language="jscript" 
        type="text/jscript">
        var message = "An error occurred. ";
        if (args.Exception) message += args.Exception.ToString();
        alert( message );
    </script>

At this point you should have a working page which uploads scans in the default PNG format and displays links to those images on your page. However, some additional work is required to be able to select image formats such as Tiff and Pdf.

Bonus: Add a selection control to choose the format

With the above infrastructure in place it is now a trivial matter to add format selection support. Most of the work involved is in creating and managing the select box of available formats.

  1. Add ComboBox for File Formats

    As just discussed, we must fist create a select tag which will be used to display the available formats for the currently selected scanner.

    File Format: <select id="ImageFormat"> </select>

    Next, must the same as the case with the ‘ScannerList’ select box, we must define some simply functions to make manipulating this select box easy:

    • GetSelectedImageFormat() returns the currently selected value in the ImageFormat select box.
    • FillImageFormatSelect() takes an array of file formats and makes the contents of that array the set of available options in the ‘ImageFormat’ select box.
    <script language="javascript" type="text/javascript">
    function GetSelectedImageFormat() {
      var formatSelect = document.getElementById("ImageFormat");
      return formatSelect.options[formatSelect.selectedIndex].value;
    }
    function FillFileFormatSelect(formatArray) {
         var formatSelect = document.getElementById("ImageFormat"); 
         formatSelect.length = 0;
         if (formatArray.length > 0) {
          for (var i = 0; i < formatArray.length; i++) {
              formatSelect.add(new Option(formatArray[i], formatArray[i]));
          }
      }
      formatSelect.selectedIndex = 0;
    }
    </script>
  2. List Scanner Specific File Formats in Combo Box when a Device is Selected

    Because we created the FillImageFormatSelect function above, this is a simple matter of two lines to our SelectedScannerChanged event. The two bolded lines bellow get an array of supported image formats from our queryable device object via its SupportedImageFormats property and pass that array in to the FillImageFormatSelect() function.

    <script language="javascript" type="text/javascript">
     
    function GetSelectedScanner() {
      var formatSelect = document.getElementById("ScannerList");
      return formatSelect.options[formatSelect.selectedIndex].value;
    }
     
    function SelectedScannerChanged() {
      var scannerName = GetSelectedScanner();
      scanningDevice = document.ScanningControl.GetDevice(scannerName);
    }
     
    function FillScannerSelect(scannerArray) {
      var scannerSelect = document.getElementById("ScannerList");
      scannerSelect.length = 0;
      if (scannerArray.length > 0) {
          for (var i = 0; i < scannerArray.length; i++) {
              scannerSelect.add(new Option(scannerArray[i], scannerArray[i]));
          }
      }
      scannerSelect.selectedIndex = 0;
      SelectedScannerChanged();
    }
     
    </script>
  3. Set Selected File Format Before Scanning

    Finally, we must add a single line to our Scan() function to set the Image format in our batch before it is submitted for processing. This line, which is bolded below, simply sets the ImageFormat property of our batch object to the text set in the ImageFormat select box.

    <script for="ScanningControl" event="ControlInitializationComplete(args)" 
        language="jscript" type="text/jscript">
      if (args.TwainIsAvailable == true) {
        var scannerArray = document.ScanningControl.GetAvailableDevices();
        FillScannerSelect(scannerArray);
      } 
    </script>

Conclusion

Congratulations, you now have a fully functional Twain scanning web page.

The functionality described in this article is just the bare minimum of what is possible with the DotTwain ActiveX control. For additional information read the ActiveX Control Overview and ActiveX Control API Reference sections of the DotTwain help file in which our control’s full functionality is documented.

image008.jpg

For more detailed examples with comments and additional functionality, take a look at our WebScanning demos which are available in the Demos section under DotTwain in your start menu.

image009.jpg

If you’d like to use DotTwain in your website, but need to evaluate more of its features, please let us know by requesting a custom proof-of-concept.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here