Tutorial: Implementing DjVu to PDF with SDK

Learning Objectives

In this tutorial, you’ll learn:

  • What the Aspose.OCR Cloud SDK is and its advantages
  • How to set up and configure the SDK in your project
  • How to use the SDK to convert DjVu files to PDF
  • How to handle errors and edge cases
  • Best practices for SDK implementation

Prerequisites

Before starting this tutorial, you should have:

  • An Aspose Cloud account (sign up for free)
  • Your Client ID and Client Secret from the Aspose Cloud dashboard
  • Basic understanding of your chosen programming language
  • A development environment set up for your language
  • A DjVu file for testing

Understanding Aspose.OCR Cloud SDK

While you can directly use the REST API for DjVu to PDF conversion (as covered in previous tutorials), Aspose provides Software Development Kits (SDKs) that simplify the integration process. These SDKs wrap all the routine operations such as:

  • Authentication and token management
  • Request formatting and sending
  • Response parsing and error handling
  • File encoding and decoding

Advantages of Using the SDK

  1. Simplified Code: Fewer lines of code needed for the same functionality
  2. Type Safety: Language-specific types and error checking
  3. Automatic Token Management: No need to handle access token generation manually
  4. Better Error Handling: Native exceptions and error information
  5. Streamlined Development: Focus on business logic rather than API details

Setting Up the SDK

Let’s set up the SDK for .NET, which is currently the primary supported SDK for DjVu to PDF conversion.

Installing the .NET SDK

For a .NET project, you can install the SDK using NuGet Package Manager:

Package Manager Console

Install-Package Aspose.OCR-Cloud

dotnet CLI

dotnet add package Aspose.OCR-Cloud

Or add the package reference directly to your .csproj file:

<ItemGroup>
    <PackageReference Include="Aspose.OCR-Cloud" Version="x.x.x" />
</ItemGroup>

Project Setup

Create a new .NET project if you don’t have one already:

dotnet new console -n DjVuToPdfConverter
cd DjVuToPdfConverter
dotnet add package Aspose.OCR-Cloud

Converting DjVu to PDF with the SDK

Now let’s implement the DjVu to PDF conversion using the SDK.

Step 1: Create a Basic Conversion Program

Create a new Program.cs file with the following code:

using Aspose.OCR.Cloud.SDK.Api;
using Aspose.OCR.Cloud.SDK.Model;
using System;
using System.IO;

namespace DjVuToPdfConverter
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Replace with your actual credentials
                string clientId = "YOUR_CLIENT_ID";
                string clientSecret = "YOUR_CLIENT_SECRET";
                
                // Path to your DjVu file
                string djvuFilePath = "sample.djvu";
                
                // Initialize the API client
                DjVu2PDFApi api = new DjVu2PDFApi(clientId, clientSecret);
                
                Console.WriteLine("Reading DjVu file...");
                byte[] fileBytes = File.ReadAllBytes(djvuFilePath);
                
                Console.WriteLine("Setting up conversion parameters...");
                OCRSettingsDjVu2PDF conversionSettings = new OCRSettingsDjVu2PDF();
                
                Console.WriteLine("Sending DjVu for conversion...");
                OCRDjVu2PDFBody requestBody = new OCRDjVu2PDFBody(fileBytes, conversionSettings);
                string taskId = api.PostDjVu2PDF(requestBody);
                
                Console.WriteLine($"DjVu file sent for conversion. Task ID: {taskId}");
                
                Console.WriteLine("Waiting for conversion to complete...");
                OCRResponse result = api.GetDjVu2PDF(taskId);
                
                Console.WriteLine($"Conversion status: {result.TaskStatus}");
                
                if (result.TaskStatus == "Completed" && result.Results != null && result.Results.Count > 0)
                {
                    Console.WriteLine("Conversion successful. Saving PDF...");
                    byte[] pdfBytes = result.Results[0].Data;
                    
                    string outputPath = "output.pdf";
                    File.WriteAllBytes(outputPath, pdfBytes);
                    Console.WriteLine($"PDF saved to {Path.GetFullPath(outputPath)}");
                }
                else if (result.Error != null && result.Error.Messages != null)
                {
                    Console.WriteLine($"Error: {string.Join(", ", result.Error.Messages)}");
                }
                else
                {
                    Console.WriteLine("Conversion not completed or no results available.");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
                Console.WriteLine(ex.StackTrace);
            }
        }
    }
}

Step 2: Build and Run the Program

Compile and run the program:

dotnet run

This basic program will:

  1. Initialize the SDK with your credentials
  2. Read a DjVu file from disk
  3. Send it for conversion
  4. Wait for the conversion to complete
  5. Save the resulting PDF

Try It Yourself

  1. Replace YOUR_CLIENT_ID and YOUR_CLIENT_SECRET with your actual credentials
  2. Ensure you have a sample.djvu file in the same directory as your program
  3. Run the program and observe the output
  4. Verify that the output.pdf file is created and can be opened

Adding Polling for Asynchronous Processing

The basic example above assumes the conversion completes quickly. In practice, you should implement polling to handle the asynchronous nature of the conversion process:

using Aspose.OCR.Cloud.SDK.Api;
using Aspose.OCR.Cloud.SDK.Model;
using System;
using System.IO;
using System.Threading;

namespace DjVuToPdfConverter
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // Replace with your actual credentials
                string clientId = "YOUR_CLIENT_ID";
                string clientSecret = "YOUR_CLIENT_SECRET";
                
                // Path to your DjVu file
                string djvuFilePath = "sample.djvu";
                
                // Initialize the API client
                DjVu2PDFApi api = new DjVu2PDFApi(clientId, clientSecret);
                
                Console.WriteLine("Reading DjVu file...");
                byte[] fileBytes = File.ReadAllBytes(djvuFilePath);
                
                Console.WriteLine("Setting up conversion parameters...");
                OCRSettingsDjVu2PDF conversionSettings = new OCRSettingsDjVu2PDF();
                
                Console.WriteLine("Sending DjVu for conversion...");
                OCRDjVu2PDFBody requestBody = new OCRDjVu2PDFBody(fileBytes, conversionSettings);
                string taskId = api.PostDjVu2PDF(requestBody);
                
                Console.WriteLine($"DjVu file sent for conversion. Task ID: {taskId}");
                
                // Polling parameters
                int maxAttempts = 12;
                int delaySeconds = 5;
                
                Console.WriteLine("Polling for conversion results...");
                OCRResponse result = null;
                
                for (int attempt = 1; attempt <= maxAttempts; attempt++)
                {
                    Console.WriteLine($"Polling attempt {attempt}/{maxAttempts}...");
                    
                    result = api.GetDjVu2PDF(taskId);
                    Console.WriteLine($"Task status: {result.TaskStatus}");
                    
                    if (result.TaskStatus == "Completed" || 
                        result.TaskStatus == "Error" ||
                        result.TaskStatus == "NotExist")
                    {
                        // Task has reached a terminal state
                        break;
                    }
                    
                    if (attempt < maxAttempts)
                    {
                        Console.WriteLine($"Waiting {delaySeconds} seconds before next attempt...");
                        Thread.Sleep(delaySeconds * 1000);
                    }
                }
                
                if (result != null && result.TaskStatus == "Completed" && 
                    result.Results != null && result.Results.Count > 0)
                {
                    Console.WriteLine("Conversion successful. Saving PDF...");
                    byte[] pdfBytes = result.Results[0].Data;
                    
                    string outputPath = "output.pdf";
                    File.WriteAllBytes(outputPath, pdfBytes);
                    Console.WriteLine($"PDF saved to {Path.GetFullPath(outputPath)}");
                }
                else if (result != null && result.Error != null && result.Error.Messages != null)
                {
                    Console.WriteLine($"Error: {string.Join(", ", result.Error.Messages)}");
                }
                else
                {
                    Console.WriteLine("Conversion timed out or no results available.");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
                Console.WriteLine(ex.StackTrace);
            }
        }
    }
}

Creating a Reusable Conversion Service

For a more professional implementation, let’s create a reusable service class that handles the conversion process:

using Aspose.OCR.Cloud.SDK.Api;
using Aspose.OCR.Cloud.SDK.Model;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DjVuToPdfConverter
{
    public class DjVuConverterService
    {
        private readonly string _clientId;
        private readonly string _clientSecret;
        private readonly DjVu2PDFApi _api;
        
        public DjVuConverterService(string clientId, string clientSecret)
        {
            _clientId = clientId;
            _clientSecret = clientSecret;
            _api = new DjVu2PDFApi(clientId, clientSecret);
        }
        
        /// <summary>
        /// Converts a DjVu file to PDF asynchronously
        /// </summary>
        /// <param name="djvuFilePath">Path to the DjVu file</param>
        /// <param name="outputPdfPath">Path where the PDF should be saved</param>
        /// <param name="maxAttempts">Maximum number of polling attempts</param>
        /// <param name="delaySeconds">Delay between polling attempts in seconds</param>
        /// <returns>True if conversion was successful, false otherwise</returns>
        public async Task<bool> ConvertDjVuToPdfAsync(
            string djvuFilePath, 
            string outputPdfPath, 
            int maxAttempts = 12, 
            int delaySeconds = 5,
            CancellationToken cancellationToken = default)
        {
            try
            {
                Console.WriteLine("Reading DjVu file...");
                byte[] fileBytes = File.ReadAllBytes(djvuFilePath);
                
                Console.WriteLine("Setting up conversion parameters...");
                OCRSettingsDjVu2PDF conversionSettings = new OCRSettingsDjVu2PDF();
                
                Console.WriteLine("Sending DjVu for conversion...");
                OCRDjVu2PDFBody requestBody = new OCRDjVu2PDFBody(fileBytes, conversionSettings);
                string taskId = _api.PostDjVu2PDF(requestBody);
                
                Console.WriteLine($"DjVu file sent for conversion. Task ID: {taskId}");
                
                Console.WriteLine("Polling for conversion results...");
                OCRResponse result = null;
                
                for (int attempt = 1; attempt <= maxAttempts; attempt++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    
                    Console.WriteLine($"Polling attempt {attempt}/{maxAttempts}...");
                    
                    result = _api.GetDjVu2PDF(taskId);
                    Console.WriteLine($"Task status: {result.TaskStatus}");
                    
                    if (result.TaskStatus == "Completed" || 
                        result.TaskStatus == "Error" ||
                        result.TaskStatus == "NotExist")
                    {
                        // Task has reached a terminal state
                        break;
                    }
                    
                    if (attempt < maxAttempts)
                    {
                        Console.WriteLine($"Waiting {delaySeconds} seconds before next attempt...");
                        await Task.Delay(delaySeconds * 1000, cancellationToken);
                    }
                }
                
                if (result != null && result.TaskStatus == "Completed" && 
                    result.Results != null && result.Results.Count > 0)
                {
                    Console.WriteLine("Conversion successful. Saving PDF...");
                    byte[] pdfBytes = result.Results[0].Data;
                    
                    File.WriteAllBytes(outputPdfPath, pdfBytes);
                    Console.WriteLine($"PDF saved to {Path.GetFullPath(outputPdfPath)}");
                    return true;
                }
                else if (result != null && result.Error != null && result.Error.Messages != null)
                {
                    Console.WriteLine($"Error: {string.Join(", ", result.Error.Messages)}");
                    return false;
                }
                else
                {
                    Console.WriteLine("Conversion timed out or no results available.");
                    return false;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An error occurred: {ex.Message}");
                Console.WriteLine(ex.StackTrace);
                return false;
            }
        }
    }
    
    class Program
    {
        static async Task Main(string[] args)
        {
            string clientId = "YOUR_CLIENT_ID";
            string clientSecret = "YOUR_CLIENT_SECRET";
            
            var converter = new DjVuConverterService(clientId, clientSecret);
            
            bool success = await converter.ConvertDjVuToPdfAsync(
                djvuFilePath: "sample.djvu",
                outputPdfPath: "output.pdf"
            );
            
            if (success)
            {
                Console.WriteLine("Conversion completed successfully!");
            }
            else
            {
                Console.WriteLine("Conversion failed.");
            }
        }
    }
}

Error Handling and Best Practices

When implementing DjVu to PDF conversion with the SDK, follow these best practices:

1. Validate Input Files

Before sending files for conversion, ensure they are valid DjVu files:

private bool IsValidDjVuFile(string filePath)
{
    if (!File.Exists(filePath))
    {
        Console.WriteLine($"File does not exist: {filePath}");
        return false;
    }
    
    // Check file extension
    if (!Path.GetExtension(filePath).Equals(".djvu", StringComparison.OrdinalIgnoreCase))
    {
        Console.WriteLine("File does not have a .djvu extension");
        return false;
    }
    
    // Check file size
    long fileSize = new FileInfo(filePath).Length;
    if (fileSize == 0)
    {
        Console.WriteLine("File is empty");
        return false;
    }
    
    if (fileSize > 100 * 1024 * 1024) // 100 MB limit example
    {
        Console.WriteLine("File exceeds the size limit of 100 MB");
        return false;
    }
    
    return true;
}

2. Implement Proper Exception Handling

Catch and handle specific exceptions:

try
{
    // SDK operations
}
catch (Aspose.OCR.Cloud.SDK.Client.ApiException apiEx)
{
    Console.WriteLine($"API Error: {apiEx.ErrorCode} - {apiEx.Message}");
    Console.WriteLine($"Response: {apiEx.ErrorContent}");
}
catch (IOException ioEx)
{
    Console.WriteLine($"File I/O Error: {ioEx.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"General Error: {ex.Message}");
}

3. Implement Timeout and Cancellation

Add timeout and cancellation support:

public async Task<bool> ConvertWithTimeout(string filePath, string outputPath, TimeSpan timeout)
{
    using (var cts = new CancellationTokenSource(timeout))
    {
        try
        {
            return await ConvertDjVuToPdfAsync(filePath, outputPath, cancellationToken: cts.Token);
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Conversion timed out");
            return false;
        }
    }
}

4. Retry Logic for Transient Failures

Implement retry logic for network issues:

public async Task<bool> ConvertWithRetry(string filePath, string outputPath, int maxRetries = 3)
{
    for (int retry = 0; retry < maxRetries; retry++)
    {
        try
        {
            return await ConvertDjVuToPdfAsync(filePath, outputPath);
        }
        catch (Exception ex) when (IsTransientException(ex))
        {
            if (retry < maxRetries - 1)
            {
                int delay = (int)Math.Pow(2, retry) * 1000; // Exponential backoff
                Console.WriteLine($"Attempt {retry + 1} failed. Retrying in {delay/1000} seconds...");
                await Task.Delay(delay);
            }
            else
            {
                Console.WriteLine($"All {maxRetries} attempts failed.");
                throw;
            }
        }
    }
    
    return false;
}

private bool IsTransientException(Exception ex)
{
    // Determine if exception is transient (network issue, temporary server error, etc.)
    return ex is System.Net.WebException || 
           ex is System.Net.Http.HttpRequestException || 
           (ex is Aspose.OCR.Cloud.SDK.Client.ApiException apiEx && 
            (apiEx.ErrorCode == 429 || apiEx.ErrorCode == 503 || apiEx.ErrorCode == 504));
}

5. Log Important Events

Implement logging to track the conversion process:

public class DjVuConverterService
{
    private readonly ILogger<DjVuConverterService> _logger;
    
    public DjVuConverterService(string clientId, string clientSecret, ILogger<DjVuConverterService> logger = null)
    {
        _clientId = clientId;
        _clientSecret = clientSecret;
        _api = new DjVu2PDFApi(clientId, clientSecret);
        _logger = logger;
    }
    
    private void LogInformation(string message)
    {
        _logger?.LogInformation(message);
        Console.WriteLine(message);
    }
    
    private void LogError(string message, Exception ex = null)
    {
        if (ex != null)
        {
            _logger?.LogError(ex, message);
            Console.WriteLine($"{message}: {ex.Message}");
        }
        else
        {
            _logger?.LogError(message);
            Console.WriteLine(message);
        }
    }
}

6. Support for Batch Processing

Add support for processing multiple files:

public async Task<Dictionary<string, bool>> BatchConvertAsync(
    IEnumerable<string> filePaths, 
    string outputDirectory, 
    CancellationToken cancellationToken = default)
{
    var results = new Dictionary<string, bool>();
    
    if (!Directory.Exists(outputDirectory))
    {
        Directory.CreateDirectory(outputDirectory);
    }
    
    foreach (var filePath in filePaths)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            LogInformation("Batch operation cancelled");
            break;
        }
        
        string fileName = Path.GetFileNameWithoutExtension(filePath);
        string outputPath = Path.Combine(outputDirectory, $"{fileName}.pdf");
        
        LogInformation($"Processing file: {filePath}");
        bool success = await ConvertDjVuToPdfAsync(filePath, outputPath, cancellationToken: cancellationToken);
        
        results[filePath] = success;
    }
    
    return results;
}

Creating a Complete Application

Let’s put everything together to create a complete console application for DjVu to PDF conversion:

using Aspose.OCR.Cloud.SDK.Api;
using Aspose.OCR.Cloud.SDK.Model;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace DjVuToPdfConverter
{
    public class DjVuConverterService
    {
        private readonly string _clientId;
        private readonly string _clientSecret;
        private readonly DjVu2PDFApi _api;
        private readonly ILogger _logger;
        
        public DjVuConverterService(string clientId, string clientSecret, ILogger logger = null)
        {
            _clientId = clientId;
            _clientSecret = clientSecret;
            _api = new DjVu2PDFApi(clientId, clientSecret);
            _logger = logger;
        }
        
        private void Log(string message, LogLevel level = LogLevel.Information)
        {
            Console.WriteLine(message);
            
            switch (level)
            {
                case LogLevel.Information:
                    _logger?.LogInformation(message);
                    break;
                case LogLevel.Error:
                    _logger?.LogError(message);
                    break;
                case LogLevel.Warning:
                    _logger?.LogWarning(message);
                    break;
            }
        }
        
        public async Task<bool> ConvertDjVuToPdfAsync(
            string djvuFilePath, 
            string outputPdfPath, 
            int maxAttempts = 12, 
            int delaySeconds = 5,
            CancellationToken cancellationToken = default)
        {
            if (!IsValidDjVuFile(djvuFilePath))
            {
                Log($"Invalid DjVu file: {djvuFilePath}", LogLevel.Error);
                return false;
            }
            
            try
            {
                Log("Reading DjVu file...");
                byte[] fileBytes = File.ReadAllBytes(djvuFilePath);
                
                Log("Setting up conversion parameters...");
                OCRSettingsDjVu2PDF conversionSettings = new OCRSettingsDjVu2PDF();
                
                Log("Sending DjVu for conversion...");
                OCRDjVu2PDFBody requestBody = new OCRDjVu2PDFBody(fileBytes, conversionSettings);
                string taskId = _api.PostDjVu2PDF(requestBody);
                
                Log($"DjVu file sent for conversion. Task ID: {taskId}");
                
                Log("Polling for conversion results...");
                OCRResponse result = null;
                
                for (int attempt = 1; attempt <= maxAttempts; attempt++)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    
                    Log($"Polling attempt {attempt}/{maxAttempts}...");
                    
                    result = _api.GetDjVu2PDF(taskId);
                    Log($"Task status: {result.TaskStatus}");
                    
                    if (result.TaskStatus == "Completed" || 
                        result.TaskStatus == "Error" ||
                        result.TaskStatus == "NotExist")
                    {
                        // Task has reached a terminal state
                        break;
                    }
                    
                    if (attempt < maxAttempts)
                    {
                        Log($"Waiting {delaySeconds} seconds before next attempt...");
                        await Task.Delay(delaySeconds * 1000, cancellationToken);
                    }
                }
                
                if (result != null && result.TaskStatus == "Completed" && 
                    result.Results != null && result.Results.Count > 0)
                {
                    Log("Conversion successful. Saving PDF...");
                    byte[] pdfBytes = result.Results[0].Data;
                    
                    // Ensure output directory exists
                    string outputDir = Path.GetDirectoryName(outputPdfPath);
                    if (!string.IsNullOrEmpty(outputDir) && !Directory.Exists(outputDir))
                    {
                        Directory.CreateDirectory(outputDir);
                    }
                    
                    File.WriteAllBytes(outputPdfPath, pdfBytes);
                    Log($"PDF saved to {Path.GetFullPath(outputPdfPath)}");
                    return true;
                }
                else if (result != null && result.Error != null && result.Error.Messages != null)
                {
                    Log($"Error: {string.Join(", ", result.Error.Messages)}", LogLevel.Error);
                    return false;
                }
                else
                {
                    Log("Conversion timed out or no results available.", LogLevel.Warning);
                    return false;
                }
            }
            catch (Exception ex)
            {
                Log($"An error occurred: {ex.Message}", LogLevel.Error);
                return false;
            }
        }
        
        public async Task<bool> ConvertWithTimeout(string filePath, string outputPath, TimeSpan timeout)
        {
            using (var cts = new CancellationTokenSource(timeout))
            {
                try
                {
                    return await ConvertDjVuToPdfAsync(filePath, outputPath, cancellationToken: cts.Token);
                }
                catch (OperationCanceledException)
                {
                    Log("Conversion timed out", LogLevel.Warning);
                    return false;
                }
            }
        }
        
        public async Task<Dictionary<string, bool>> BatchConvertAsync(
            IEnumerable<string> filePaths, 
            string outputDirectory, 
            CancellationToken cancellationToken = default)
        {
            var results = new Dictionary<string, bool>();
            
            if (!Directory.Exists(outputDirectory))
            {
                Directory.CreateDirectory(outputDirectory);
            }
            
            foreach (var filePath in filePaths)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    Log("Batch operation cancelled", LogLevel.Warning);
                    break;
                }
                
                string fileName = Path.GetFileNameWithoutExtension(filePath);
                string outputPath = Path.Combine(outputDirectory, $"{fileName}.pdf");
                
                Log($"Processing file: {filePath}");
                bool success = await ConvertDjVuToPdfAsync(filePath, outputPath, cancellationToken: cancellationToken);
                
                results[filePath] = success;
            }
            
            return results;
        }
        
        private bool IsValidDjVuFile(string filePath)
        {
            if (!File.Exists(filePath))
            {
                Log($"File does not exist: {filePath}", LogLevel.Error);
                return false;
            }
            
            // Check file extension
            if (!Path.GetExtension(filePath).Equals(".djvu", StringComparison.OrdinalIgnoreCase))
            {
                Log("File does not have a .djvu extension", LogLevel.Error);
                return false;
            }
            
            // Check file size
            long fileSize = new FileInfo(filePath).Length;
            if (fileSize == 0)
            {
                Log("File is empty", LogLevel.Error);
                return false;
            }
            
            if (fileSize > 100 * 1024 * 1024) // 100 MB limit example
            {
                Log("File exceeds the size limit of 100 MB", LogLevel.Error);
                return false;
            }
            
            return true;
        }
        
        private bool IsTransientException(Exception ex)
        {
            // Determine if exception is transient (network issue, temporary server error, etc.)
            return ex is System.Net.WebException || 
                  ex is System.Net.Http.HttpRequestException || 
                  (ex is Aspose.OCR.Cloud.SDK.Client.ApiException apiEx && 
                   (apiEx.ErrorCode == 429 || apiEx.ErrorCode == 503 || apiEx.ErrorCode == 504));
        }
    }
    
    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                // Configuration
                string clientId = "YOUR_CLIENT_ID";
                string clientSecret = "YOUR_CLIENT_SECRET";
                
                // Parse command line arguments
                if (args.Length < 1)
                {
                    Console.WriteLine("Usage: DjVuToPdfConverter <inputPath> [outputPath]");
                    Console.WriteLine("  inputPath: Path to a DjVu file or directory containing DjVu files");
                    Console.WriteLine("  outputPath: (Optional) Output file or directory for PDFs");
                    return;
                }
                
                string inputPath = args[0];
                string outputPath = args.Length > 1 ? args[1] : null;
                
                var converter = new DjVuConverterService(clientId, clientSecret);
                
                if (File.Exists(inputPath))
                {
                    // Single file conversion
                    string defaultOutputPath = outputPath ?? 
                        Path.Combine(
                            Path.GetDirectoryName(inputPath), 
                            $"{Path.GetFileNameWithoutExtension(inputPath)}.pdf"
                        );
                    
                    Console.WriteLine($"Converting single file: {inputPath} to {defaultOutputPath}");
                    
                    bool success = await converter.ConvertDjVuToPdfAsync(
                        djvuFilePath: inputPath,
                        outputPdfPath: defaultOutputPath
                    );
                    
                    Console.WriteLine(success 
                        ? "Conversion completed successfully!" 
                        : "Conversion failed."
                    );
                }
                else if (Directory.Exists(inputPath))
                {
                    // Batch conversion
                    string defaultOutputDir = outputPath ?? Path.Combine(inputPath, "converted");
                    
                    Console.WriteLine($"Converting all DjVu files in: {inputPath}");
                    Console.WriteLine($"Output directory: {defaultOutputDir}");
                    
                    string[] djvuFiles = Directory.GetFiles(inputPath, "*.djvu", SearchOption.TopDirectoryOnly);
                    
                    if (djvuFiles.Length == 0)
                    {
                        Console.WriteLine("No DjVu files found in the specified directory.");
                        return;
                    }
                    
                    Console.WriteLine($"Found {djvuFiles.Length} DjVu files.");
                    var results = await converter.BatchConvertAsync(djvuFiles, defaultOutputDir);
                    
                    int successCount = 0;
                    foreach (var result in results)
                    {
                        if (result.Value)
                        {
                            successCount++;
                        }
                    }
                    
                    Console.WriteLine($"Conversion completed: {successCount} of {results.Count} files converted successfully.");
                }
                else
                {
                    Console.WriteLine($"Input path not found: {inputPath}");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"An unexpected error occurred: {ex.Message}");
                Console.WriteLine(ex.StackTrace);
            }
        }
    }
}

What You’ve Learned

In this tutorial, you’ve learned:

  • How to use the Aspose.OCR Cloud SDK for DjVu to PDF conversion
  • How to set up a basic conversion program using the SDK
  • How to implement polling for asynchronous processing
  • How to handle errors and edge cases
  • How to create a reusable conversion service
  • Best practices for production-ready implementations
  • How to support batch processing of multiple files

Next Steps

Now that you’ve learned how to implement DjVu to PDF conversion using the SDK, consider:

  1. Integrating with your applications: Add this functionality to your existing document processing systems
  2. Creating a user interface: Build a web or desktop UI for the converter
  3. Adding more advanced features: Support for custom conversion settings, progress reporting, etc.
  4. Implementing more robust error handling: Add detailed logging and recovery mechanisms

Further Practice

  • Create a Windows Forms or WPF application with a drag-and-drop interface for conversion
  • Implement a web service that accepts DjVu files and returns PDFs
  • Add support for converting other document formats using related Aspose APIs
  • Benchmark conversion performance with different file sizes and types

Helpful Resources

Have questions about this tutorial? Feel free to post on our support forum.