Building a .NET RESTful Service with Dynamsoft's Document, Barcode, and MRZ SDKs

Xiao Ling - Oct 27 '23 - - Dev Community

RESTful service can be accessed from anywhere with an internet connection, irrespective of platform or device. Deploying a commercial SDK as a RESTful service can simplify integration, improve accessibility, and provide better control over the deployment environment and usage. In this article, we'll delve into how you can effortlessly integrate Dynamsoft's Document, Barcode, and MRZ SDKs into a RESTful service with .NET.

Prerequisites

Initiate a .NET Web API Project

In .NET SDK, a Web API template is used to create a web service that follows the REST architectural style. We can use the following command to quickly create a new project in the terminal:

dotnet new webapi -n DynamsoftRestfulService
Enter fullscreen mode Exit fullscreen mode

Then install the dependencies for the project:

cd DynamsoftRestfulService
dotnet add package Twain.Wia.Sane.Scanner --version 1.0.1
dotnet add package DocumentScannerSDK --version 1.1.0
dotnet add package BarcodeQRCodeSDK --version 2.3.4
dotnet add package MrzScannerSDK --version 1.3.0

dotnet add package OpenCvSharp4 --version 4.6.0.20220608
dotnet add package OpenCvSharp4.Extensions --version 4.5.5.20211231
dotnet add package OpenCvSharp4.runtime.win --version 4.6.0.20220608 
Enter fullscreen mode Exit fullscreen mode

The OpenCV package is used to decode the image stream uploaded by the client.

By default, the application will only respond to requests originating from the same machine on which it's running. This means it listens only to localhost (127.0.0.1). To allow the application to listen to requests from other machines, we need to add the following code to the Program.cs file:

builder.WebHost.ConfigureKestrel(serverOptions =>
{
    serverOptions.Listen(System.Net.IPAddress.Any, 5000);
});
Enter fullscreen mode Exit fullscreen mode

CORS (Cross-Origin Resource Sharing) is a mechanism that allows a web application running at one origin to access the resources from a server running at a different origin. We need to enable CORS and configure it to accept requests from other origins.

  1. Install the required package:

      dotnet add package Microsoft.AspNetCore.Cors
    
  2. Add the following code to the Program.cs file:

      builder.Services.AddCors(options =>
      {
          options.AddPolicy("AllowSpecificOrigin",
              builder =>
              {
                  builder.AllowAnyOrigin()
                    .AllowAnyHeader()
                    .AllowAnyMethod();
              });
      });
    
      app.UseCors("AllowSpecificOrigin");
    

Now, run dotnet run to start the app, then open your browser and go to http://localhost:5000/WeatherForecast. If you see the following response, the app is functioning as expected:

[
    {
        "date": "2023-10-25",
        "temperatureC": 25,
        "temperatureF": 76,
        "summary": "Cool"
    },
    {
        "date": "2023-10-26",
        "temperatureC": -20,
        "temperatureF": -3,
        "summary": "Hot"
    },
    {
        "date": "2023-10-27",
        "temperatureC": -3,
        "temperatureF": 27,
        "summary": "Warm"
    },
    {
        "date": "2023-10-28",
        "temperatureC": -17,
        "temperatureF": 2,
        "summary": "Balmy"
    },
    {
        "date": "2023-10-29",
        "temperatureC": 21,
        "temperatureF": 69,
        "summary": "Warm"
    }
]
Enter fullscreen mode Exit fullscreen mode

dotnet web api project

The /WeatherForecast endpoint is defined in the WeatherForecastController.cs file. We can follow the same pattern to add our own endpoints.

Integrating Dynamsoft SDKs into the RESTful Service

Create a LicenseManager.cs file to manage the license keys for Dynamsoft SDKs:

using System.ComponentModel;
using Dynamsoft;


public class LicenseManager
{
    public static string dwt = "LICENSE-KEY";
    public static string dbr = "LICENSE-KEY";
    public static string dlr = "LICENSE-KEY";
    public static string ddn = "LICENSE-KEY";

    public static void Init()
    {
        BarcodeQRCodeReader.InitLicense(dbr);
        MrzScanner.InitLicense(dlr);
        DocumentScanner.InitLicense(ddn);
    }
}

Enter fullscreen mode Exit fullscreen mode

Then add LicenseManager.Init(); to the program.cs file.

In the Controllers folder, create five files: ProductController.cs, DwtController.cs, DbrController.cs, DlrController.cs, and DdnController.cs. These files will contain the endpoints for the respective SDKs.

Product List Endpoints

Add an HTTP GET endpoint to retrieve the list of available Dynamsoft products:

[Route("dynamsoft/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
    private static List<String> products = new List<String>
    {
        "Dynamic Web TWAIN",
        "Dynamsoft Barcode Reader",
        "Dynamsoft Label Recognizer",
        "Dynamsoft Document Normalizer",
    };

    [HttpGet]
    public ActionResult<IEnumerable<String>> Get()
    {
        return products;
    }

}
Enter fullscreen mode Exit fullscreen mode

Dynamic Web TWAIN Endpoints

Import the packages:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using Twain.Wia.Sane.Scanner;
using System.Text.Json;
Enter fullscreen mode Exit fullscreen mode

Initialize the controller:

[Route("dynamsoft/[controller]")]
[ApiController]
public class DwtController : ControllerBase
{
    private static ScannerController scannerController = new ScannerController();
    private static string host = "http://127.0.0.1:18622";
}
Enter fullscreen mode Exit fullscreen mode

The host variable is the address of the Dynamsoft service. If you're running the service on a different machine, you'll need to change the address accordingly.

Add an HTTP GET endpoint to retrieve the list of available scanners:

[HttpGet]
[Route("GetDevices")]
public async Task<ActionResult<Dictionary<string, object>>> GetDevices()
{
    var scanners = await scannerController.GetDevices(host);
    if (scanners.Count == 0)
    {
        return Ok("No devices found");
    }
    return Ok(scanners);
}
Enter fullscreen mode Exit fullscreen mode

Add an HTTP POST endpoint to initiate a scanning job and return the job ID:

[HttpPost]
[Route("ScanDocument")]
public async Task<IActionResult> ScanDocument()
{
    if (Request.ContentType == null) return BadRequest("No content type specified");

    if (Request.ContentType.Contains("application/json"))
    {
        using (StreamReader reader = new StreamReader(Request.Body))
        {
            var json = await reader.ReadToEndAsync();

            Dictionary<string, object>? parameters = JsonSerializer.Deserialize<Dictionary<string, object>>(json);
            if (parameters == null) return BadRequest("No content found");

            parameters["license"] = LicenseManager.dwt;
            string jobId = await scannerController.ScanDocument(host, parameters);

            return Ok(jobId);
        }
    }
    else
    {
        return BadRequest("Unsupported content type");
    }
}
Enter fullscreen mode Exit fullscreen mode

Add an HTTP GET endpoint to fetch the image stream for a specific job and return the image stream:

[HttpGet]
[Route("GetImageStream/{jobId}")]
public async Task<ActionResult<Dictionary<string, object>>> GetImageStream(string jobId)
{
    byte[] bytes = await scannerController.GetImageStream(host, jobId);
    if (bytes.Length == 0)
    {
        return Ok("No image found");
    }
    else
    {
        return File(bytes, "application/octet-stream");
    }
}
Enter fullscreen mode Exit fullscreen mode

Dynamsoft Barcode Reader Endpoints

Import the packages:

using Dynamsoft;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using static Dynamsoft.BarcodeQRCodeReader;
using BarcodeResult = Dynamsoft.BarcodeQRCodeReader.Result;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Runtime.InteropServices;
Enter fullscreen mode Exit fullscreen mode

Initialize the controller:

[Route("dynamsoft/[controller]")]
[ApiController]
public class DbrController : ControllerBase
{
    private BarcodeQRCodeReader barcodeScanner;

    public DbrController()
    {
        barcodeScanner = BarcodeQRCodeReader.Create();
    }
}
Enter fullscreen mode Exit fullscreen mode

Add an HTTP POST endpoint to decode barcodes from an uploaded image stream and return the reading results:

[HttpPost]
[Route("DecodeBarcode")]
public async Task<IActionResult> DecodeBarcode()
{
    if (Request.ContentType == null) return BadRequest("No content type specified");

    if (Request.ContentType.Contains("multipart/form-data"))
    {
        var form = await Request.ReadFormAsync();
        var file = form.Files[0];
        if (file.Length == 0)
        {
            return BadRequest("Empty file received");
        }

        using (var memoryStream = new MemoryStream())
        {
            await file.CopyToAsync(memoryStream);
            memoryStream.Position = 0;
            Mat mat = Mat.FromStream(memoryStream, ImreadModes.Color);

            int length = mat.Cols * mat.Rows * mat.ElemSize();
            byte[] bytes = new byte[length];
            Marshal.Copy(mat.Data, bytes, 0, length);
            BarcodeResult[]? results = barcodeScanner.DecodeBuffer(bytes, mat.Cols, mat.Rows, (int)mat.Step(), BarcodeQRCodeReader.ImagePixelFormat.IPF_RGB_888);
            if (results == null || results.Length == 0)
            {
                return Ok("No barcode found");
            }

            return Ok(results);
        }
    }
    else
    {
        return BadRequest("Unsupported content type");
    }
}
Enter fullscreen mode Exit fullscreen mode

Dynamsoft Label Recognizer Endpoints

Import the packages:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using Dynamsoft;
using static Dynamsoft.MrzScanner;
using Result = Dynamsoft.MrzScanner.Result;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using System.Runtime.InteropServices;
Enter fullscreen mode Exit fullscreen mode

Initialize the controller:

[Route("dynamsoft/[controller]")]
[ApiController]
public class DlrController : ControllerBase
{
    private MrzScanner mrzScanner;

    public DlrController()
    {
        mrzScanner = MrzScanner.Create();
        mrzScanner.LoadModel();
    }
}
Enter fullscreen mode Exit fullscreen mode

Add an HTTP POST endpoint to recognize MRZ (Machine Readable Zone) from an uploaded image stream and return the MRZ text results:

[HttpPost]
[Route("DetectMrz")]
public async Task<IActionResult> DetectMrz()
{
    if (Request.ContentType == null) return BadRequest("No content type specified");

    if (Request.ContentType.Contains("multipart/form-data"))
    {
        var form = await Request.ReadFormAsync();
        var file = form.Files[0];
        if (file.Length == 0)
        {
            return BadRequest("Empty file received");
        }

        using (var memoryStream = new MemoryStream())
        {
            await file.CopyToAsync(memoryStream);
            memoryStream.Position = 0;
            Mat mat = Mat.FromStream(memoryStream, ImreadModes.Color);

            int length = mat.Cols * mat.Rows * mat.ElemSize();
            byte[] bytes = new byte[length];
            Marshal.Copy(mat.Data, bytes, 0, length);
            Result[]? results = mrzScanner.DetectBuffer(bytes, mat.Cols, mat.Rows, (int)mat.Step(), MrzScanner.ImagePixelFormat.IPF_RGB_888);
            if (results == null || results.Length == 0)
            {
                return Ok("No MRZ found");
            }

            string[] lines = new string[results.Length];
            var index = 0;
            foreach (Result result in results)
            {
                lines[index++] = result.Text;
            }

            MrzResult info = MrzParser.Parse(lines);

            return Ok(info.ToJson());
        }
    }
    else
    {
        return BadRequest("Unsupported content type");
    }
}
Enter fullscreen mode Exit fullscreen mode

Dynamsoft Document Normalizer Endpoints

Import the packages:

using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using Dynamsoft;
using OpenCvSharp;
using OpenCvSharp.Extensions;
using static Dynamsoft.DocumentScanner;
using DocResult = Dynamsoft.DocumentScanner.Result;
using System.Runtime.InteropServices;
Enter fullscreen mode Exit fullscreen mode

Initialize the controller:

public class DdnController : ControllerBase
{
    private DocumentScanner documentScanner;

    public DdnController()
    {
        documentScanner = DocumentScanner.Create();
        documentScanner.SetParameters(DocumentScanner.Templates.color);
    }
}
Enter fullscreen mode Exit fullscreen mode

Add an HTTP POST endpoint to rectify a document from an uploaded image stream and return a rectified image:

[HttpPost]
[Route("rectifyDocument")]
public async Task<IActionResult> rectifyDocument()
{
    if (Request.ContentType == null) return BadRequest("No content type specified");

    if (Request.ContentType.Contains("multipart/form-data"))
    {
        var form = await Request.ReadFormAsync();
        var file = form.Files[0];
        if (file.Length == 0)
        {
            return BadRequest("Empty file received");
        }

        using (var memoryStream = new MemoryStream())
        {
            await file.CopyToAsync(memoryStream);
            memoryStream.Position = 0;
            Mat mat = Mat.FromStream(memoryStream, ImreadModes.Color);

            int length = mat.Cols * mat.Rows * mat.ElemSize();
            byte[] bytes = new byte[length];
            Marshal.Copy(mat.Data, bytes, 0, length);
            DocResult[]? results = documentScanner.DetectBuffer(bytes, mat.Cols, mat.Rows, (int)mat.Step(), DocumentScanner.ImagePixelFormat.IPF_RGB_888);

            if (results != null)
            {
                DocResult result = results[0];

                NormalizedImage image = documentScanner.NormalizeBuffer(bytes, mat.Cols, mat.Rows, (int)mat.Step(), DocumentScanner.ImagePixelFormat.IPF_RGB_888, result.Points);
                if (image != null && image.Data != null)
                {
                    Mat newMat;
                    if (image.Stride < image.Width)
                    {
                        // binary
                        byte[] data = image.Binary2Grayscale();
                        newMat = new Mat(image.Height, image.Width, MatType.CV_8UC1, data);
                    }
                    else if (image.Stride >= image.Width * 3)
                    {
                        // color
                        newMat = new Mat(image.Height, image.Width, MatType.CV_8UC3, image.Data);
                    }
                    else
                    {
                        // grayscale
                        newMat = new Mat(image.Height, image.Stride, MatType.CV_8UC1, image.Data);
                    }

                    byte[] buffer;
                    Cv2.ImEncode(".jpg", newMat, out buffer);
                    return File(buffer, "application/octet-stream");
                }

            }
        }

        return Ok("No document found");
    }
    else
    {
        return BadRequest("Unsupported content type");
    }
}
Enter fullscreen mode Exit fullscreen mode

REST API Table

Method Endpoint Parameters Response Description
GET /dynamsoft/product - Product list Retrieve all Dynamsoft products.
GET /dynamsoft/dwt/GetDevices - Scanner list List available scanners.
POST /dynamsoft/dwt/ScanDocument Scanner config Job ID Initiate a scanning job.
GET /dynamsoft/dwt/GetImageStream/{jobId} jobId Image stream Fetch image stream for a specific job.
POST /dynamsoft/dbr/DecodeBarcode Image stream Barcode results Decode barcodes using the Dynamsoft Barcode Reader.
POST /dynamsoft/ddn/rectifyDocument Image stream Mrz results Detect MRZ from an image with Dynamsoft Label Recognizer.
POST /dynamsoft/dlr/DetectMrz Image stream Rectified document image Rectify a document with Dynamsoft Document Normalizer.

Creating an HTML5 Web App for Testing the RESTful Service

Create an input element for entering the RESTful service URL. As the connection is established, the available products will be listed in the dropdown menu.

HTML

<div class="row">
    <div>
        <label>Enter host address: </label>
        <input type="text" id="host" placeholder="http://192.168.8.72:5000/">
        <button onclick="connect()">connect</button>
    </div>
</div>

<div class="row">
    <div>
        <select onchange="selectChanged()" id="dropdown">
        </select>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

JavaScript

let host = placeholder = 'http://192.168.8.72:5000/';
let dropdown = document.getElementById("dropdown");
function selectChanged() {
    switchProduct(dropdown.value)
}

async function connect() {
    dropdown.innerHTML = "";
    host = document.getElementById("host").value == "" ? placeholder : document.getElementById("host").value;

    try {
        const response = await fetch(host + 'dynamsoft/product', {
            method: 'GET',
            headers: {
                'Content-Type': 'application/json'
            }
        });

        if (response.status == 200) {
            const products = await response.json();

            products.forEach(element => {
                let optionElement = document.createElement("option");
                optionElement.value = element;
                optionElement.text = element;
                dropdown.appendChild(optionElement);
            });
            switchProduct(dropdown.value)
        }
        else {
            hideAll();
        }

    } catch (error) {
        console.log(error);
    }
}
Enter fullscreen mode Exit fullscreen mode

Create a container for testing Dynamic Web TWAIN endpoints

HTML

<div class="container" id="dwt">
    <div class="row">
        <div>
            <button onclick="getDevices()">Get Devices</button>
            <select id="sources">
            </select>
            <button onclick="acquireImage()">Scan Documents</button>
        </div>

    </div>

    <div class="row">
        <div class="full-img">
            <img id="scanner-image">
        </div>
    </div>

    <div class="row">
        <div class="thumb-bar" id="thumb-bar">
            <div class="thumb-box" id="thumb-box">
            </div>
        </div>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

JavaScript

let selectSources = document.getElementById("sources");
let devices = [];

async function getDevices() {
    document.getElementById("loading-indicator").style.display = "flex";
    selectSources.innerHTML = "";
    let url = host + 'dynamsoft/dwt/getdevices';
    const response = await fetch(url, { "method": "GET" });

    if (response.status == 200) {

        try {
            let json = await response.json();
            if (json) {
                devices = json;
                json.forEach(element => {
                    let option = document.createElement("option");
                    option.text = element['name'];
                    option.value = element['name'];
                    selectSources.add(option);
                });
            }
        } catch (error) {
            console.log(error)
        }

    }
    document.getElementById("loading-indicator").style.display = "none";
}

async function acquireImage() {
    let url = host + 'dynamsoft/dwt/ScanDocument';
    if (devices.length > 0 && selectSources.selectedIndex >= 0) {
        let parameters = {
            device: devices[selectSources.selectedIndex]['device'],
            config: {
                IfShowUI: false,
                PixelType: 2,
                //XferCount: 1,
                //PageSize: 1,
                Resolution: 200,
                IfFeederEnabled: false,
                IfDuplexEnabled: false,
            }
        };

        let response = await fetch(url, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(parameters)
        });

        const contentType = response.headers.get('Content-Type');
        const result = await response.text();

        url = host + 'dynamsoft/dwt/GetImageStream/' + result;

        response = await fetch(url, { method: 'GET' });

        let imageBlob = await response.blob();
        let img = document.getElementById('scanner-image');
        url = URL.createObjectURL(imageBlob);
        img.src = url;

        let option = document.createElement("option");
        option.selected = true;
        option.text = url;
        option.value = url;

        let thumbnails = document.getElementById("thumb-box");
        let newImage = document.createElement('img');
        newImage.setAttribute('src', url);
        if (thumbnails != null) {
            thumbnails.appendChild(newImage);
            newImage.addEventListener('click', e => {
                if (e != null && e.target != null) {
                    let target = e.target;
                    img.src = target.src;
                }
            });
        }
    }

}
Enter fullscreen mode Exit fullscreen mode

Create a container for testing Dynamsoft Barcode Reader endpoints

HTML

<div class="container" id="dbr">
    <div class="row">
        <div>
            <input type="file" id="barcode-file" accept="image/*" />
            <button onclick="decodeBarcode()">Read Barcode</button>
        </div>

    </div>

    <div class="row">
        <div id="imageview">
            <img id="barcode-image" src="https://via.placeholder.com/640x480" />
        </div>
    </div>

    <div class="row">
        <div>
            <textarea id="barcode-result"></textarea>
        </div>
    </div>

</div>
Enter fullscreen mode Exit fullscreen mode

JavaScript

document.getElementById("barcode-file").addEventListener("change", function () {
    document.getElementById('barcode-result').innerHTML = '';
    let currentFile = this.files[0];
    if (currentFile == null) {
        return;
    }
    var fr = new FileReader();
    fr.onload = function () {
        let image = document.getElementById('barcode-image');
        image.src = fr.result;
    }
    fr.readAsDataURL(currentFile);
});

async function decodeBarcode() {
    let url = host + 'dynamsoft/dbr/DecodeBarcode';

    const input = document.getElementById('barcode-file');
    const file = input.files[0];

    if (!file) {
        return;
    }

    const formData = new FormData();
    formData.append('image', file);

    let response = await fetch(url, {
        method: 'POST',
        body: formData
    });

    if (response.headers.get('Content-Type').includes('application/json')) {
        let data = await response.json();
        let content = 'total barcode(s) found: ' + data.length;
        let index = 0;
        data.forEach(element => {
            content += '\n';
            content += index + ". text: " + element['text'] + ", format: " + element['format1'];
            index += 1;
        });
        document.getElementById('barcode-result').innerHTML = content;
    }
    else if (response.headers.get('Content-Type').includes('text/plain')) {
        let data = await response.text();
        document.getElementById('barcode-result').innerHTML = data;
    }
}
Enter fullscreen mode Exit fullscreen mode

Create a container for testing Dynamsoft Label Recognizer endpoints

HTML

<div class="container" id="dlr">
    <div class="row">
        <div>
            <input type="file" id="mrz-file" accept="image/*" />
            <button onclick="detectMrz()">Detect MRZ</button>
        </div>

    </div>

    <div class="row">
        <div id="imageview">
            <img id="mrz-image" src="https://via.placeholder.com/640x480" />
        </div>
    </div>

    <div class="row">
        <div>
            <textarea id="mrz-result"></textarea>
        </div>
    </div>

</div>
Enter fullscreen mode Exit fullscreen mode

JavaScript

document.getElementById("mrz-file").addEventListener("change", function () {
    document.getElementById('barcode-result').innerHTML = '';
    let currentFile = this.files[0];
    if (currentFile == null) {
        return;
    }
    var fr = new FileReader();
    fr.onload = function () {
        let image = document.getElementById('mrz-image');
        image.src = fr.result;
    }
    fr.readAsDataURL(currentFile);
});

async function detectMrz() {
    let url = host + 'dynamsoft/dlr/DetectMrz';

    const input = document.getElementById('mrz-file');
    const file = input.files[0];

    if (!file) {
        return;
    }

    const formData = new FormData();
    formData.append('image', file);

    let response = await fetch(url, {
        method: 'POST',
        body: formData
    });

    if (response.headers.get('Content-Type').includes('application/json')) {
        let data = await response.json();
        document.getElementById('mrz-result').innerHTML = JSON.stringify(data);
    }
    else if (response.headers.get('Content-Type').includes('text/plain')) {
        let data = await response.text();
        document.getElementById('mrz-result').innerHTML = data;
    }
}
Enter fullscreen mode Exit fullscreen mode

Create a container for testing Dynamsoft Document Normalizer endpoints

HTML

<div class="container" id="ddn">
    <div class="row">
        <div>
            <input type="file" id="document-file" accept="image/*" />
            <button onclick="rectifyDocument()">Rectify Document</button>
        </div>

    </div>

    <div class="row">
        <div id="imageview">
            <img id="document-image" src="https://via.placeholder.com/640x480" />
        </div>
    </div>

    <div class="row">
        <div>
            <textarea id="document-result"></textarea>
            <img id="document-rectified-image" />
        </div>
    </div>

</div>
Enter fullscreen mode Exit fullscreen mode

JavaScript

document.getElementById("document-file").addEventListener("change", function () {
    let currentFile = this.files[0];
    if (currentFile == null) {
        return;
    }
    var fr = new FileReader();
    fr.onload = function () {
        let image = document.getElementById('document-image');
        image.src = fr.result;
    }
    fr.readAsDataURL(currentFile);
});

async function rectifyDocument() {
    let url = host + 'dynamsoft/ddn/rectifyDocument';

    const input = document.getElementById('document-file');
    const file = input.files[0];

    if (!file) {
        return;
    }

    const formData = new FormData();
    formData.append('image', file);

    let response = await fetch(url, {
        method: 'POST',
        body: formData
    });

    if (response.headers.get('Content-Type').includes('text/plain')) {
        let data = await response.text();
        document.getElementById('document-result').innerHTML = data;

        let divElement = document.getElementById("document-result");
        divElement.style.display = "block";

        divElement = document.getElementById("document-rectified-image");
        divElement.style.display = "none";
    }
    else if (response.headers.get('Content-Type').includes('application/octet-stream')) {
        let data = await response.blob();
        let img = document.getElementById('document-rectified-image');
        let url = URL.createObjectURL(data);
        img.src = url;

        let divElement = document.getElementById("document-rectified-image");
        divElement.style.display = "block";

        divElement = document.getElementById("document-result");
        divElement.style.display = "none";
    }
}
Enter fullscreen mode Exit fullscreen mode

Source Code

https://github.com/yushulx/dynamsoft-sdk-webapi-restful-service/tree/main/dotnet

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player