Large size Document opening taking too long to open

Dear Team,

Below is my method for opening the document. When I am open the .pptx URL of size 188mb it takes 9-10 mins to open and .pdf of size 25mb takes 2-3 min to open. Can please identify where I am missing the logic to reduce the document opening time. Please suggest me best way to open the document at highest speed.

    public async Task<IActionResult> OpenDocument(
    string docpath = "",
    string guid = "",
    string watermark = "",
    string UserName = "",
    string Password = "",
    string FileId = "")
    {
        var totalSw = System.Diagnostics.Stopwatch.StartNew();

        string pathToFile = string.Empty;
        string _annotations = string.Empty;
        string psno = Request.Cookies["OneViewID"];
        string tempFile = string.Empty;

        System.Diagnostics.Debug.WriteLine("[DocOpen] ================= START =================");

        try
        {
            // ── PATH RESOLUTION ───────────────────────────────────────────────
            var pathSw = System.Diagnostics.Stopwatch.StartNew();

            if (!string.IsNullOrEmpty(docpath))
            {
                try
                {
                    pathToFile = Decrypt(CleanToDirty(docpath));
                }
                catch
                {
                    pathToFile = docpath;
                }
            }
            else
            {
                if (Request.Cookies["OneViewID"] == null)
                {
                    return Json(new
                    {
                        success = false,
                        message = "Unauthorized"
                    });
                }

                var dbSw = System.Diagnostics.Stopwatch.StartNew();

                var _fcshis = await _dbContext.FCSHIS
                    .FirstOrDefaultAsync(x => x.GUID == guid);

                dbSw.Stop();

                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] FCSHIS Query: {dbSw.ElapsedMilliseconds}ms");

                if (_fcshis == null)
                {
                    return Json(new
                    {
                        success = false,
                        message = "Invalid guid."
                    });
                }

                if (DateTime.Now >
                    _fcshis.OpenDate.Value.AddMinutes(_fcshis.MaxMinAllowed.Value))
                {
                    return Json(new
                    {
                        success = false,
                        message = "Time expired"
                    });
                }

                long documentId = Convert.ToInt64(_fcshis.DocumentId);

                pathToFile = _fcshis.DocumentPath;

                var annSw = System.Diagnostics.Stopwatch.StartNew();

                _annotations = await _dbContext.FCSANN
                    .Where(x => x.PSNO == psno && x.DocumentId == documentId)
                    .Select(x => x.Annotations)
                    .FirstOrDefaultAsync() ?? string.Empty;

                annSw.Stop();

                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] Annotation Query: {annSw.ElapsedMilliseconds}ms");
            }

            pathSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Path Resolution: {pathSw.ElapsedMilliseconds}ms");

            // ── FILE EXISTENCE ────────────────────────────────────────────────
            bool isUrlPath =
                pathToFile.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
                pathToFile.StartsWith("https://", StringComparison.OrdinalIgnoreCase);

            if (!isUrlPath && !System.IO.File.Exists(pathToFile))
            {
                Response.StatusCode = 404;

                return Json(new
                {
                    success = false,
                    message = $"File does not exist: {pathToFile}"
                });
            }

            // ── FILE INFO ─────────────────────────────────────────────────────
            var fileInfoSw = System.Diagnostics.Stopwatch.StartNew();

            string fileExtension = Path.GetExtension(pathToFile).ToLower();

            bool isLargeFile = false;
            long fileSizeBytes = 0;

            if (isUrlPath)
            {
                try
                {
                    using var httpHead = new HttpClient();

                    httpHead.Timeout = TimeSpan.FromSeconds(15);

                    var headRequest = new HttpRequestMessage(HttpMethod.Head, pathToFile);

                    var headResponse = await httpHead.SendAsync(headRequest);

                    if (headResponse.Content.Headers.ContentLength.HasValue)
                    {
                        fileSizeBytes = headResponse.Content.Headers.ContentLength.Value;

                        isLargeFile = fileSizeBytes > 10 * 1024 * 1024;
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(
                        $"[DocOpen] HEAD Request Failed: {ex.Message}");
                }
            }
            else
            {
                var fi = new FileInfo(pathToFile);

                if (fi.Exists)
                {
                    fileSizeBytes = fi.Length;

                    isLargeFile = fileSizeBytes > 10 * 1024 * 1024;
                }
            }

            fileInfoSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] File Info: {fileInfoSw.ElapsedMilliseconds}ms");

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] File Size: {fileSizeBytes / 1024 / 1024}MB");

            // ── LICENSES ──────────────────────────────────────────────────────
            var licenseSw = System.Diagnostics.Stopwatch.StartNew();

            var licenses = _cache.GetOrCreate("_docViewerLicenses", entry =>
            {
                entry.Priority = CacheItemPriority.NeverRemove;

                return new List<string>
                {
                    Path.Combine(_hostingEnvironment.WebRootPath, "Doconut.Viewer.lic"),
                    Path.Combine(_hostingEnvironment.WebRootPath, "Doconut.Viewer.Search.lic"),
                    Path.Combine(_hostingEnvironment.WebRootPath, "Doconut.Viewer.Annotation.lic")
                };
            });

            licenseSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] License Load: {licenseSw.ElapsedMilliseconds}ms");

            var docViewer = new Viewer(_cache, _accessor, licenses);

            // ── BASE CONFIG ───────────────────────────────────────────────────
            var configSw = System.Diagnostics.Stopwatch.StartNew();

            var config = _cache.GetOrCreate($"_baseConfig_{fileExtension}", entry =>
            {
                entry.Priority = CacheItemPriority.NeverRemove;

                return GetBaseConfig(new FileInfo("viewFile" + fileExtension));
            });

            configSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Base Config Load: {configSw.ElapsedMilliseconds}ms");

            // ── RESOLUTION ────────────────────────────────────────────────────
            int resolution;

            if (fileExtension == ".ppt" || fileExtension == ".pptx")
            {
                if (fileSizeBytes > 150 * 1024 * 1024)
                    resolution = 72;
                else if (fileSizeBytes > 75 * 1024 * 1024)
                    resolution = 85;
                else if (fileSizeBytes > 25 * 1024 * 1024)
                    resolution = 95;
                else
                    resolution = 110;
            }
            else
            {
                resolution = 100;
            }
            resolution = 200; // set to solve print generation zoom bug erported by kishan
            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Resolution Selected: {resolution} DPI");

            // ── OPTIONS ───────────────────────────────────────────────────────
            var documentOptions = new DocOptions
            {
                Password = "",
                ImageResolution = resolution,
                TimeOut = isLargeFile ? 600 : 120
            };

            string cachePath = Path.Combine(_hostingEnvironment.WebRootPath, Startup.webFarmFolder);
            if (Startup.useWebfarm)
            {
                documentOptions.IsWebfarm = true;
                documentOptions.WebfarmPath = cachePath;
                documentOptions.TimeOut = isLargeFile ? 300 : 60;  // override timeout for webfarm
            }

            // ── CLEANUP TEMP FILES ────────────────────────────────────────────
            var cleanupSw = System.Diagnostics.Stopwatch.StartNew();

            try
            {
                string tempFolder =
                    Path.Combine(_hostingEnvironment.WebRootPath, "DoconutTempFiles");

                if (!Directory.Exists(tempFolder))
                    Directory.CreateDirectory(tempFolder);

                var oldFiles = Directory
                    .GetFiles(tempFolder, "DOCONUT_TEMP_*")
                    .Where(x =>
                        System.IO.File.GetCreationTime(x) <
                        DateTime.Now.AddHours(-2))
                    .ToList();

                foreach (var oldFile in oldFiles)
                {
                    try
                    {
                        System.IO.File.Delete(oldFile);
                    }
                    catch { }
                }
            }
            catch { }

            cleanupSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Temp Cleanup: {cleanupSw.ElapsedMilliseconds}ms");

            // ── OPEN DOCUMENT ─────────────────────────────────────────────────
            string token = string.Empty;

            if (isUrlPath)
            {
                string tempFolder =
                    Path.Combine(_hostingEnvironment.WebRootPath, "DoconutTempFiles");

                if (!Directory.Exists(tempFolder))
                    Directory.CreateDirectory(tempFolder);

                tempFile = Path.Combine(
                    tempFolder,
                    $"DOCONUT_TEMP_{DateTime.Now:yyyyMMddHHmmssfff}_{Guid.NewGuid():N}{fileExtension}");

                // ── DOWNLOAD ──────────────────────────────────────────────────
                var downloadSw = System.Diagnostics.Stopwatch.StartNew();

                using (var httpClient = new HttpClient())
                {
                    httpClient.Timeout = TimeSpan.FromMinutes(15);

                    if (!string.IsNullOrWhiteSpace(UserName) &&
                        !string.IsNullOrWhiteSpace(Password))
                    {
                        var byteArray =
                            Encoding.ASCII.GetBytes($"{UserName}:{Password}");

                        httpClient.DefaultRequestHeaders.Authorization =
                            new System.Net.Http.Headers.AuthenticationHeaderValue(
                                "Basic",
                                Convert.ToBase64String(byteArray));
                    }

                    using var response = await httpClient.GetAsync(
                        pathToFile,
                        HttpCompletionOption.ResponseHeadersRead);

                    if (!response.IsSuccessStatusCode)
                    {
                        return Json(new
                        {
                            success = false,
                            message =
                                $"Failed to download file. HTTP {(int)response.StatusCode}"
                        });
                    }

                    await using var networkStream =
                        await response.Content.ReadAsStreamAsync();

                    await using var fileStream = new FileStream(
                        tempFile,
                        FileMode.Create,
                        FileAccess.Write,
                        FileShare.None,
                        bufferSize: 1024 * 1024,
                        useAsync: true);

                    // ── FILE WRITE ────────────────────────────────────────────
                    var fileWriteSw = System.Diagnostics.Stopwatch.StartNew();

                    await networkStream.CopyToAsync(fileStream);

                    await fileStream.FlushAsync();

                    fileWriteSw.Stop();

                    long writtenSizeMb = 0;

                    try
                    {
                        if (System.IO.File.Exists(tempFile))
                        {
                            var writtenFileInfo = new FileInfo(tempFile);

                            writtenSizeMb = writtenFileInfo.Length / 1024 / 1024;
                        }
                    }
                    catch { }

                    System.Diagnostics.Debug.WriteLine(
                        $"[DocOpen] File Write Completed | Size: {writtenSizeMb}MB | Time: {fileWriteSw.ElapsedMilliseconds}ms");
                }

                downloadSw.Stop();

                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] File Download Total: {downloadSw.ElapsedMilliseconds}ms");

                // ── DOCONUT OPEN ──────────────────────────────────────────────
                var openSw = System.Diagnostics.Stopwatch.StartNew();

                token = await Task.Run(() =>
                {
                    return docViewer.OpenDocument(
                        tempFile,
                        config,
                        documentOptions);
                });

                openSw.Stop();

                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] Doconut OpenDocument: {openSw.ElapsedMilliseconds}ms");

                // ── TEMP DELETE ───────────────────────────────────────────────
                var deleteSw = System.Diagnostics.Stopwatch.StartNew();

                try
                {
                    if (System.IO.File.Exists(tempFile))
                        System.IO.File.Delete(tempFile);
                }
                catch { }

                deleteSw.Stop();

                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] Temp Delete: {deleteSw.ElapsedMilliseconds}ms");
            }
            else
            {
                var localOpenSw = System.Diagnostics.Stopwatch.StartNew();

                token = await Task.Run(() =>
                {
                    return docViewer.OpenDocument(
                        pathToFile,
                        config,
                        documentOptions);
                });

                localOpenSw.Stop();

                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] Local OpenDocument: {localOpenSw.ElapsedMilliseconds}ms");
            }

            // ── POST PROCESSING ───────────────────────────────────────────────
            var postSw = System.Diagnostics.Stopwatch.StartNew();

            var tasks = new List<Task>();

            if (!isLargeFile)
            {
                // ── ANNOTATIONS ───────────────────────────────────────────────
                tasks.Add(Task.Run(() =>
                {
                    var annotationSw = System.Diagnostics.Stopwatch.StartNew();

                    try
                    {
                        if (!string.IsNullOrEmpty(_annotations))
                        {
                            XmlDocument xml =
                                JsonConvert.DeserializeXmlNode(_annotations);

                            docViewer.LoadAnnotationXML(xml);
                        }

                        annotationSw.Stop();

                        System.Diagnostics.Debug.WriteLine(
                            $"[Annotations] Completed in {annotationSw.ElapsedMilliseconds}ms");
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(
                            $"[Annotations] Skipped: {ex.Message}");
                    }
                }));

                // ── SEARCH ────────────────────────────────────────────────────
                tasks.Add(Task.Run(() =>
                {
                    var searchSw = System.Diagnostics.Stopwatch.StartNew();

                    try
                    {
                        var srhbytes = docViewer.SaveSearch();

                        if (srhbytes?.Length > 0)
                        {
                            string raw = System.Text.Encoding.UTF8.GetString(srhbytes);

                            string clean =
                                System.Text.RegularExpressions.Regex.Replace(
                                    raw,
                                    @"[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]",
                                    string.Empty);

                            byte[] cleanBytes =
                                System.Text.Encoding.UTF8.GetBytes(clean);

                            docViewer.LoadSearchData(
                                new MemoryStream(cleanBytes)
                                {
                                    Position = 0
                                });
                        }

                        searchSw.Stop();

                        System.Diagnostics.Debug.WriteLine(
                            $"[Search] Completed in {searchSw.ElapsedMilliseconds}ms");
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(
                            $"[Search] Skipped: {ex.Message}");
                    }
                }));

                // ── EXPORT PNG ────────────────────────────────────────────────
                if (Startup.useWebfarm)
                {
                    tasks.Add(Task.Run(() =>
                    {
                        var pngSw = System.Diagnostics.Stopwatch.StartNew();

                        try
                        {
                            docViewer.ExportToPng(cachePath);

                            pngSw.Stop();

                            System.Diagnostics.Debug.WriteLine(
                                $"[ExportToPng] Completed in {pngSw.ElapsedMilliseconds}ms");
                        }
                        catch (Exception ex)
                        {
                            System.Diagnostics.Debug.WriteLine(
                                $"[ExportToPng] Failed: {ex.Message}");
                        }
                    }));
                }
            }
            else
            {
                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] Large file — skipping Search, Annotations, ExportToPng");
            }

            if (tasks.Count > 0)
            {
                await Task.WhenAll(tasks);
            }

            postSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Post Processing Total: {postSw.ElapsedMilliseconds}ms");

            // ── CACHE ─────────────────────────────────────────────────────────
            var cacheSw = System.Diagnostics.Stopwatch.StartNew();

            var cacheOpts = new MemoryCacheEntryOptions
            {
                SlidingExpiration = TimeSpan.FromMinutes(30)
            };

            _cache.Set("docViewer-" + token, docViewer, cacheOpts);

            _cache.Set("OriginalFilePath-" + token, pathToFile, cacheOpts);

            cacheSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Cache Save: {cacheSw.ElapsedMilliseconds}ms");

            totalSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] TOTAL TIME: {totalSw.ElapsedMilliseconds}ms");

            System.Diagnostics.Debug.WriteLine("[DocOpen] ================= END =================");

            return Json(new
            {
                success = true,
                token = token
            });
        }
        catch (Exception e)
        {
            totalSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] ERROR after {totalSw.ElapsedMilliseconds}ms");

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] ERROR: {e}");

            Response.StatusCode = 400;

            return Json(new
            {
                success = false,
                message = e.Message
            });
        }
        finally
        {
            if (!string.IsNullOrEmpty(tempFile) &&
                System.IO.File.Exists(tempFile))
            {
                try
                {
                    System.IO.File.Delete(tempFile);
                }
                catch { }
            }
        }
    }

@Mohit_Tandel

Thank you for sharing the code and the details. From the code, it appears that you are using an ASP.NET Core MVC application, and possibly the Doconut .NET Standard package.

Could you please confirm which Doconut package/framework you are using and the exact version number?

Regarding the opening time, there are several factors that can affect performance, especially with large files such as a 188 MB PPTX file. The opening speed depends not only on the code logic but also on the server resources, including CPU, RAM, disk speed, network speed, and whether the document is being loaded from a local path or downloaded from a remote URL.

If the documents are not confidential, please send us the PPTX and PDF files so we can test them on our side and better understand the performance behavior.

Yes this is ASP .NET Core application. We are currently using doconut.NETStandard 25.10.0 Package.

Sorry I cant share the files as they are confidentials.

And there is another issue I have noticed that after publishing when 188mb ppt gets opens after 8-10 mins of sometimes it take more than 12 mins. below URL gets opened and viewer disappear. basically after opening the docuement, document viewer disappears. see Image attached
image.jpg (147.4 KB)

https://abcd.testexaple.com:4443/DocImage.axd?page=6&zoom=100&token=4b58062f-afb6-472e-95ee-15cc647a9e03&rnd=211778487859682&format=png

@Mohit_Tandel

Thank you for the confirmation. Since the files are confidential, we understand that you cannot share them.

Regarding the 188 MB PPTX file, could you please confirm how many pages/slides the PowerPoint document contains?

Also, could you please share the server resources where the application is running, specifically:

  • RAM
  • CPU
  • Hosting environment, for example, IIS, Azure, VM, dedicated server, etc.

This information is important because large PowerPoint files can require significant memory and processing time during rendering, especially when converting pages to images for the viewer.

In addition, could you please confirm whether you are using the standard Doconut Viewer mode or the Web Farm/distributed mode?

About the URL you mentioned. This is the internal image handler used by Doconut to render document pages. If the viewer disappears after the document finally opens, it may indicate that the page rendering process is being interrupted, timing out, or running out of available server resources.

Please send us the details mentioned above so we can better understand if this behavior is related.

@gabriel.vega

Thank you for your response.

The PowerPoint document contains approximately 67 slides.

The application is hosted on IIS, and currently we are using the standard Doconut Viewer mode (not Web Farm/distributed mode).

At the moment, I do not have access to the exact production server specifications. However, on my local system where the same behavior is reproducible, the configuration is:

  • RAM: 32 GB
  • CPU: Intel i5-7400 @ 3.00 GHz
  • Storage: SSD + HDD
  • OS: Windows 64-bit

I have already shared the current implementation/configuration from our side. Our main objective is to understand whether we are missing any recommended configuration, rendering settings, caching approach, timeout handling, or best practices specifically for handling very large PPTX files in Doconut.

Could you please review the shared implementation and guide us with the best possible approach or recommended logic for opening and handling large PowerPoint files efficiently?

Additionally, if there are any specific Doconut settings, IIS configurations, cache strategies, or optimizations recommended for large presentations, kindly let us know.

@Mohit_Tandel

Thank you for the additional details. The information you shared is helpful. Since the original PowerPoint file is confidential, we understand that you cannot share it with us.

Based on your description, this appears to be related to the size and complexity of the PowerPoint document, not only the number of slides. A 188 MB PPTX with approximately 67 slides may contain high-resolution images, embedded objects, charts, custom fonts, or other elements that can significantly increase the rendering time and memory usage.

If possible, and only if allowed on your side, you may also share a sanitized version of the PowerPoint file, or a similar test file with no confidential content that reproduces the same behavior. You may set the post as private for additional privacy. This would help us perform a more accurate analysis.

We will get back to you once we have more findings or recommendations from our development team.

Hi @gabriel.vega,

Unfortunately, I cannot share the original PPTX file because it contains sensitive customer data. However, I am sharing an AI-generated PPTX sample for reference. Please note that this sample does not contain graphics-heavy content, so it opens much faster than the original file.
https://drive.google.com/drive/folders/1pwISELwUXwjsG9SSEkwVKKdHorEbn1Xm?usp=drive_link

Our main concern is related to performance with very large PPTX files.

Previously, our client had an older document viewer implementation that was able to open the same 188 MB PPTX file within approximately 2 minutes and 30 seconds. That viewer had a URL exposure/security issue, and since the client does not have the source code for it, we developed a new viewer project using Doconut.

The current issue is:

  • The old viewer could render the document in around 2.5 minutes.
  • Our current Doconut-based implementation is taking more than 8 minutes.
  • After loading for several minutes, the viewer disappears and a URL like the following gets opened:
https://ecomapplication.lthed.com:2345/DocImage.axd?thumb=1&width=150&token=74057c29-73a9-4fff-b0d7-ead66375b07a&page=14&rnd=581778820778412&format=png

Our expectation is not necessarily to achieve sub-2-minute loading, but at least something manageable. Even an additional 10–15 seconds compared to the old viewer would still be acceptable for us.

This issue has been ongoing for quite some time, and the customer is continuously asking for a resolution. We have already tried multiple optimizations from our side but have been unable to solve it. If this issue remains unresolved, there is a risk that the project may be dropped, which we definitely want to avoid.

That is why we are sharing our implementation details here, hoping you can guide us if we are missing something important or using Doconut incorrectly.

Current setup details:

Startup.cs configuration:

bool useWebfarm = false;

app.MapWhen(
    context => context.Request.Path.ToString().EndsWith("DocImage.axd"),
    appBranch =>
    {
        if (useWebfarm)
        {
            appBranch.UseDoconutWebFarm(new WebFarmOptions
            {
                Path = Path.Combine(env.WebRootPath, webFarmFolder),
                PageWaitTimeSeconds = 5,
                StartWaitFromPage = 5
            });
        }
        else
        {
            appBranch.UseDoconut(new DoconutOptions
            {
                UnSafeMode = true,
                ShowDoconutInfo = true
            });
        }
    });

PPT/PPTX configuration:

config = new PptConfig
{
    DefaultRender = false,
    AllowSearch = false
};

Dynamic resolution handling:

  • 150MB+ → 72 DPI
  • 75MB+ → 85 DPI
  • 25MB+ → 95 DPI
  • Otherwise → 110 DPI

Below is our current OpenDocument() method. Kindly help us identify if there is any issue in our logic, missing configuration, or any recommended optimization for handling very large PPTX files in Doconut.

Another issue we noticed today:

.eml files are also taking unusually long to open which is hardly below 100kb. the same is open local system within 7–8 seconds where as the same is taking long time around 4 to 5 minutes in the deployed production environment.

Any urgent guidance or recommendations would be greatly appreciated.

public async Task<IActionResult> OpenDocument(
string docpath = "",
string guid = "",
string watermark = "",
string UserName = "",
string Password = "",
string FileId = "")
{
    var totalSw = System.Diagnostics.Stopwatch.StartNew();

    string pathToFile = string.Empty;
    string _annotations = string.Empty;
    string psno = Request.Cookies["OneViewID"];
    string tempFile = string.Empty;

    System.Diagnostics.Debug.WriteLine("[DocOpen] ================= START =================");

    try
    {
        // ── PATH RESOLUTION ───────────────────────────────────────────────
        var pathSw = System.Diagnostics.Stopwatch.StartNew();

        if (!string.IsNullOrEmpty(docpath))
        {
            try
            {
                pathToFile = Decrypt(CleanToDirty(docpath));
            }
            catch
            {
                pathToFile = docpath;
            }
            string DeniedDrives = _configuration.GetValue<string>("DeniedDrives");
            if (!string.IsNullOrEmpty(DeniedDrives))
            {
                var deniedDriveList = DeniedDrives.Split(',', StringSplitOptions.RemoveEmptyEntries);
                var fileDrive = Path.GetPathRoot(pathToFile).Replace("\\", "").Replace(":", "").ToUpper();
                if (deniedDriveList.Contains(fileDrive))
                    return Json(new { success = false, message = $"Access to the {fileDrive} drive is denied." });
            }
        }
        else
        {
            if (Request.Cookies["OneViewID"] == null)
            {
                return Json(new
                {
                    success = false,
                    message = "Unauthorized"
                });
            }

            var dbSw = System.Diagnostics.Stopwatch.StartNew();

            var _fcshis = await _dbContext.FCSHIS
                .FirstOrDefaultAsync(x => x.GUID == guid);

            dbSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] FCSHIS Query: {dbSw.ElapsedMilliseconds}ms");

            if (_fcshis == null)
            {
                return Json(new
                {
                    success = false,
                    message = "Invalid guid."
                });
            }

            if (DateTime.Now >
                _fcshis.OpenDate.Value.AddMinutes(_fcshis.MaxMinAllowed.Value))
            {
                return Json(new
                {
                    success = false,
                    message = "Time expired"
                });
            }

            long documentId = Convert.ToInt64(_fcshis.DocumentId);

            pathToFile = _fcshis.DocumentPath;

            var annSw = System.Diagnostics.Stopwatch.StartNew();

            _annotations = await _dbContext.FCSANN
                .Where(x => x.PSNO == psno && x.DocumentId == documentId)
                .Select(x => x.Annotations)
                .FirstOrDefaultAsync() ?? string.Empty;

            annSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Annotation Query: {annSw.ElapsedMilliseconds}ms");
        }

        pathSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] Path Resolution: {pathSw.ElapsedMilliseconds}ms");

        // ── FILE EXISTENCE ────────────────────────────────────────────────
        bool isUrlPath =
            pathToFile.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
            pathToFile.StartsWith("https://", StringComparison.OrdinalIgnoreCase);

        if (!isUrlPath && !System.IO.File.Exists(pathToFile))
        {
            Response.StatusCode = 404;

            return Json(new
            {
                success = false,
                message = $"File does not exist: {pathToFile}"
            });
        }

        // ── FILE INFO ─────────────────────────────────────────────────────
        var fileInfoSw = System.Diagnostics.Stopwatch.StartNew();

        string fileExtension = Path.GetExtension(pathToFile).ToLower();

        bool isLargeFile = false;
        long fileSizeBytes = 0;

        if (isUrlPath)
        {
            try
            {
                using var httpHead = new HttpClient();

                httpHead.Timeout = TimeSpan.FromSeconds(15);

                var headRequest = new HttpRequestMessage(HttpMethod.Head, pathToFile);

                var headResponse = await httpHead.SendAsync(headRequest);

                if (headResponse.Content.Headers.ContentLength.HasValue)
                {
                    fileSizeBytes = headResponse.Content.Headers.ContentLength.Value;

                    isLargeFile = fileSizeBytes > 15 * 1024 * 1024;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] HEAD Request Failed: {ex.Message}");
            }
        }
        else
        {
            var fi = new FileInfo(pathToFile);

            if (fi.Exists)
            {
                fileSizeBytes = fi.Length;

                isLargeFile = fileSizeBytes > 15 * 1024 * 1024;
            }
        }

        fileInfoSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] File Info: {fileInfoSw.ElapsedMilliseconds}ms");

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] File Size: {fileSizeBytes / 1024 / 1024}MB");

        // ── LICENSES ──────────────────────────────────────────────────────
        var licenseSw = System.Diagnostics.Stopwatch.StartNew();

        var licenses = _cache.GetOrCreate("_docViewerLicenses", entry =>
        {
            entry.Priority = CacheItemPriority.NeverRemove;

            return new List<string>
            {
                Path.Combine(_hostingEnvironment.WebRootPath, "Doconut.Viewer.lic"),
                Path.Combine(_hostingEnvironment.WebRootPath, "Doconut.Viewer.Search.lic"),
                Path.Combine(_hostingEnvironment.WebRootPath, "Doconut.Viewer.Annotation.lic")
            };
        });

        licenseSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] License Load: {licenseSw.ElapsedMilliseconds}ms");

        var docViewer = new Viewer(_cache, _accessor, licenses);

        string Watermark = string.Empty;
        if (string.IsNullOrEmpty(FileId))
        {
            string defaultWaterMark = _configuration.GetValue<string>("WaterMark")!;
            string baseWatermark = string.IsNullOrEmpty(watermark) ? defaultWaterMark : watermark;
            string label = string.IsNullOrEmpty(psno) ? baseWatermark : $"{baseWatermark} {psno}";
            Watermark = $"^{label}~Red~45~Verdana~80~-45";
        }

        // ── BASE CONFIG ───────────────────────────────────────────────────
        var configSw = System.Diagnostics.Stopwatch.StartNew();

        //var config = _cache.GetOrCreate($"_baseConfig_{fileExtension}", entry =>
        //{
        //    entry.Priority = CacheItemPriority.NeverRemove;

        //    return GetBaseConfig(new FileInfo("viewFile" + fileExtension));
        //});
        BaseConfig config = GetBaseConfig(new FileInfo("viewFile" + fileExtension));

        configSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] Base Config Load: {configSw.ElapsedMilliseconds}ms");

        // ── RESOLUTION ────────────────────────────────────────────────────
        int resolution;

        if (fileExtension == ".ppt" || fileExtension == ".pptx")
        {
            if (fileSizeBytes > 150 * 1024 * 1024)
                resolution = 72;
            else if (fileSizeBytes > 75 * 1024 * 1024)
                resolution = 85;
            else if (fileSizeBytes > 25 * 1024 * 1024)
                resolution = 95;
            else
                resolution = 110;
        }
        else
        {
            resolution = 110;
        }
        //resolution = 110; // set to solve print generation zoom bug erported by kishan
        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] Resolution Selected: {resolution} DPI");

        // ── OPTIONS ───────────────────────────────────────────────────────
        var documentOptions = new DocOptions
        {
            Password = "",
            ImageResolution = resolution,
            Watermark = Watermark,
            TimeOut = isLargeFile ? 600 : 120
        };

        string cachePath = Path.Combine(_hostingEnvironment.WebRootPath, Startup.webFarmFolder);
        if (Startup.useWebfarm)
        {
            documentOptions.IsWebfarm = true;
            documentOptions.WebfarmPath = cachePath;
            documentOptions.TimeOut = isLargeFile ? 300 : 60;  // override timeout for webfarm
        }

        // ── CLEANUP TEMP FILES ────────────────────────────────────────────
        var cleanupSw = System.Diagnostics.Stopwatch.StartNew();

        try
        {
            string tempFolder =
                Path.Combine(_hostingEnvironment.WebRootPath, "DoconutTempFiles");

            if (!Directory.Exists(tempFolder))
                Directory.CreateDirectory(tempFolder);

            var oldFiles = Directory
                .GetFiles(tempFolder, "DOCONUT_TEMP_*")
                .Where(x =>
                    System.IO.File.GetCreationTime(x) <
                    DateTime.Now.AddHours(-2))
                .ToList();

            foreach (var oldFile in oldFiles)
            {
                try
                {
                    System.IO.File.Delete(oldFile);
                }
                catch { }
            }
        }
        catch { }

        cleanupSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] Temp Cleanup: {cleanupSw.ElapsedMilliseconds}ms");

        // ── OPEN DOCUMENT ─────────────────────────────────────────────────
        string token = string.Empty;

        if (isUrlPath)
        {
            string tempFolder =
                Path.Combine(_hostingEnvironment.WebRootPath, "DoconutTempFiles");

            if (!Directory.Exists(tempFolder))
                Directory.CreateDirectory(tempFolder);

            tempFile = Path.Combine(
                tempFolder,
                $"DOCONUT_TEMP_{DateTime.Now:yyyyMMddHHmmssfff}_{Guid.NewGuid():N}{fileExtension}");

            // ── DOWNLOAD ──────────────────────────────────────────────────
            var downloadSw = System.Diagnostics.Stopwatch.StartNew();

            using (var httpClient = new HttpClient())
            {
                httpClient.Timeout = TimeSpan.FromMinutes(15);

                if (!string.IsNullOrWhiteSpace(UserName) &&
                    !string.IsNullOrWhiteSpace(Password))
                {
                    var byteArray =
                        Encoding.ASCII.GetBytes($"{UserName}:{Password}");

                    httpClient.DefaultRequestHeaders.Authorization =
                        new System.Net.Http.Headers.AuthenticationHeaderValue(
                            "Basic",
                            Convert.ToBase64String(byteArray));
                }

                using var response = await httpClient.GetAsync(
                    pathToFile,
                    HttpCompletionOption.ResponseHeadersRead);

                if (!response.IsSuccessStatusCode)
                {
                    return Json(new
                    {
                        success = false,
                        message =
                            $"Failed to download file. HTTP {(int)response.StatusCode}"
                    });
                }

                await using var networkStream =
                    await response.Content.ReadAsStreamAsync();

                await using var fileStream = new FileStream(
                    tempFile,
                    FileMode.Create,
                    FileAccess.Write,
                    FileShare.None,
                    bufferSize: 1024 * 1024,
                    useAsync: true);

                // ── FILE WRITE ────────────────────────────────────────────
                var fileWriteSw = System.Diagnostics.Stopwatch.StartNew();

                await networkStream.CopyToAsync(fileStream);

                await fileStream.FlushAsync();

                fileWriteSw.Stop();

                long writtenSizeMb = 0;

                try
                {
                    if (System.IO.File.Exists(tempFile))
                    {
                        var writtenFileInfo = new FileInfo(tempFile);

                        writtenSizeMb = writtenFileInfo.Length / 1024 / 1024;
                    }
                }
                catch { }

                System.Diagnostics.Debug.WriteLine(
                    $"[DocOpen] File Write Completed | Size: {writtenSizeMb}MB | Time: {fileWriteSw.ElapsedMilliseconds}ms");
            }

            downloadSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] File Download Total: {downloadSw.ElapsedMilliseconds}ms");

            // ── DOCONUT OPEN ──────────────────────────────────────────────
            var openSw = System.Diagnostics.Stopwatch.StartNew();

            token = await Task.Run(() =>
            {
                return docViewer.OpenDocument(
                    tempFile,
                    config,
                    documentOptions);
            });

            openSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Doconut OpenDocument: {openSw.ElapsedMilliseconds}ms");

            // ── TEMP DELETE ───────────────────────────────────────────────
            var deleteSw = System.Diagnostics.Stopwatch.StartNew();

            try
            {
                if (System.IO.File.Exists(tempFile))
                    System.IO.File.Delete(tempFile);
            }
            catch { }

            deleteSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Temp Delete: {deleteSw.ElapsedMilliseconds}ms");
        }
        else
        {
            var localOpenSw = System.Diagnostics.Stopwatch.StartNew();

            token = await Task.Run(() =>
            {
                return docViewer.OpenDocument(
                    pathToFile,
                    config,
                    documentOptions);
            });

            localOpenSw.Stop();

            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Local OpenDocument: {localOpenSw.ElapsedMilliseconds}ms");
        }

        // ── POST PROCESSING ───────────────────────────────────────────────
        var postSw = System.Diagnostics.Stopwatch.StartNew();

        var tasks = new List<Task>();

        if (!isLargeFile)
        {
            // ── ANNOTATIONS ───────────────────────────────────────────────
            tasks.Add(Task.Run(() =>
            {
                var annotationSw = System.Diagnostics.Stopwatch.StartNew();

                try
                {
                    if (!string.IsNullOrEmpty(_annotations))
                    {
                        XmlDocument xml =
                            JsonConvert.DeserializeXmlNode(_annotations);

                        docViewer.LoadAnnotationXML(xml);
                    }

                    annotationSw.Stop();

                    System.Diagnostics.Debug.WriteLine(
                        $"[Annotations] Completed in {annotationSw.ElapsedMilliseconds}ms");
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(
                        $"[Annotations] Skipped: {ex.Message}");
                }
            }));

            // ── SEARCH ────────────────────────────────────────────────────
            tasks.Add(Task.Run(() =>
            {
                var searchSw = System.Diagnostics.Stopwatch.StartNew();

                try
                {
                    var srhbytes = docViewer.SaveSearch();

                    if (srhbytes?.Length > 0)
                    {
                        string raw = System.Text.Encoding.UTF8.GetString(srhbytes);

                        string clean =
                            System.Text.RegularExpressions.Regex.Replace(
                                raw,
                                @"[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]",
                                string.Empty);

                        byte[] cleanBytes =
                            System.Text.Encoding.UTF8.GetBytes(clean);

                        docViewer.LoadSearchData(
                            new MemoryStream(cleanBytes)
                            {
                                Position = 0
                            });
                    }

                    searchSw.Stop();

                    System.Diagnostics.Debug.WriteLine(
                        $"[Search] Completed in {searchSw.ElapsedMilliseconds}ms");
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(
                        $"[Search] Skipped: {ex.Message}");
                }
            }));

            // ── EXPORT PNG ────────────────────────────────────────────────
            if (Startup.useWebfarm)
            {
                tasks.Add(Task.Run(() =>
                {
                    var pngSw = System.Diagnostics.Stopwatch.StartNew();

                    try
                    {
                        docViewer.ExportToPng(cachePath);

                        pngSw.Stop();

                        System.Diagnostics.Debug.WriteLine(
                            $"[ExportToPng] Completed in {pngSw.ElapsedMilliseconds}ms");
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine(
                            $"[ExportToPng] Failed: {ex.Message}");
                    }
                }));
            }
        }
        else
        {
            System.Diagnostics.Debug.WriteLine(
                $"[DocOpen] Large file — skipping Search, Annotations, ExportToPng");
        }

        if (tasks.Count > 0)
        {
            await Task.WhenAll(tasks);
        }

        postSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] Post Processing Total: {postSw.ElapsedMilliseconds}ms");

        // ── CACHE ─────────────────────────────────────────────────────────
        var cacheSw = System.Diagnostics.Stopwatch.StartNew();

        var cacheOpts = new MemoryCacheEntryOptions
        {
            SlidingExpiration = TimeSpan.FromMinutes(30)
        };

        _cache.Set("docViewer-" + token, docViewer, cacheOpts);

        _cache.Set("OriginalFilePath-" + token, pathToFile, cacheOpts);

        cacheSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] Cache Save: {cacheSw.ElapsedMilliseconds}ms");

        totalSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] TOTAL TIME: {totalSw.ElapsedMilliseconds}ms");

        System.Diagnostics.Debug.WriteLine("[DocOpen] ================= END =================");

        return Json(new
        {
            success = true,
            token = token
        });
    }
    catch (Exception e)
    {
        totalSw.Stop();

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] ERROR after {totalSw.ElapsedMilliseconds}ms");

        System.Diagnostics.Debug.WriteLine(
            $"[DocOpen] ERROR: {e}");

        Response.StatusCode = 400;

        return Json(new
        {
            success = false,
            message = e.Message
        });
    }
    finally
    {
        if (!string.IsNullOrEmpty(tempFile) &&
            System.IO.File.Exists(tempFile))
        {
            try
            {
                System.IO.File.Delete(tempFile);
            }
            catch { }
        }
    }
}

@Mohit_Tandel

Thank you for the detailed information and for sharing the sample PPTX file.

Our development team tested the PPTX sample you provided, as well as other large PowerPoint files containing multiple high-resolution images, in order to compare the behavior.

In our internal tests, those files opened in approximately 15 seconds on average.

For reference, we used test server specifications similar to yours:

  • CPU: 8 cores @ 3.30 GHz
  • RAM: 32 GB
  • Storage: SSD
  • OS: Windows 64-bit

These specifications should be enough for normal PPTX rendering, but for very large PowerPoint files, server conditions can still have a significant impact. In addition to CPU and RAM, it is also important to make sure that the operating system has enough free disk space in a preferably SSD.

Regarding Web Farm mode, since you are currently not using Web Farm, that is fine and actually preferable for this scenario. Web Farm/distributed mode is useful for specific deployment architectures, but it can introduce additional overhead. For this specific performance case, the standard Doconut Viewer mode should provide better performance.

One important point we noticed is the PPT configuration.

For large PPT/PPTX files, we recommend using the following configuration:

config = new PptConfig
{
    DefaultRender = true,
    AllowSearch = false
};

The reason is the following:

With:

DefaultRender = true

Doconut uses the PowerPoint rendering pipeline directly. In simple terms, this is closer to:

PowerPoint slide -> image

This is generally faster for PPT/PPTX viewing.

With:

DefaultRender = false

Doconut internally converts the PowerPoint document to PDF first and then displays it through the PDF viewer pipeline. In simple terms, this is closer to:

PowerPoint -> full PDF conversion -> PDF viewer

This approach can be slower for large PPTX files, especially when the document contains many images, embedded objects, charts, or complex slide layouts.

So, for your case, we strongly recommend avoiding DefaultRender = false for large PPTX files and testing again with DefaultRender = true.

Regarding the issue where the viewer disappears, and a DocImage.axd?... URL opens directly in the browser, this appears to be related to the JavaScript viewer configuration.

The viewer was configured with:

debugMode: true

When debugMode is enabled and an image fails to load, the Doconut JavaScript viewer may redirect the browser directly to the failed DocImage.axd request for debugging purposes. That is why the user is taken out of the viewer page and sees a URL like:

DocImage.axd?thumb=1&width=150&token=...&page=14&format=png

For production usage, please set:

debugMode: false

For very large documents, we also recommend using lazy loading behavior instead of loading too much content at once.

Suggested viewer configuration:

objctlDoc = $("#div_viewer").docViewer(
{
    debugMode: false,

    // The viewer does not add all pages and thumbnails to the DOM at once.
    // It loads them in blocks, which is better for large documents.
    largeDoc: true,

    // cacheEnabled=true:
    // - smoother navigation for small/medium documents
    // - more anticipated requests to DocImage.axd
    // - more server load
    // - more browser memory usage
    //
    // cacheEnabled=false:
    // - loads only what the user is actually viewing
    // - less pressure on the server
    // - better for very large files
    cacheEnabled: false,

    // autoLoad=true:
    // - preloads/renders the whole document
    // - useful if you want everything ready for navigation/printing
    // - very expensive for large PPTX files
    // - can overload the server and browser
    //
    // autoLoad=false:
    // - loads on demand
    // - recommended for large documents
    autoLoad: false
});

Please also review the TimeOut value in DocOptions.

For example:

var documentOptions = new DocOptions
{
    ImageResolution = 72,
    TimeOut = 600,
    Watermark = "" // only for benchmark testing
};

If the timeout is too low, the document instance may be closed too early for very large documents. Please choose a timeout value appropriate for your server capacity and the size/complexity of the files being opened.

For performance testing, we also recommend temporarily disabling the watermark:

Watermark = ""

The watermark can increase rendering cost because it needs to be applied to the rendered pages. This does not mean you cannot use watermarking in production, but it is better to disable it during benchmark tests so we can isolate the PPTX rendering time.

Recommendations:

  1. Avoid DefaultRender = false for large PPTX files.
  2. Use AllowSearch = false if search is not required.
  3. Use ImageResolution = 72 for very large PPTX files.
  4. Use largeDoc: true.
  5. Use cacheEnabled: false for huge documents.
  6. Use autoLoad: false to avoid preloading the entire file.
  7. Disable watermark.
  8. Do not use Task.Run as a performance optimization. It does not make the render faster; it only moves the work to another thread.

Suggested configuration for your large PPTX test:

config = new PptConfig
{
    DefaultRender = true,
    AllowSearch = false
};

var documentOptions = new DocOptions
{
    ImageResolution = 72,
    TimeOut = 600,
    Watermark = "" // only for benchmark testing
};

And on the JavaScript side:

objctlDoc = $("#div_viewer").docViewer(
{
    debugMode: false,
    largeDoc: true,
    cacheEnabled: false,
    autoLoad: false
});

Please test the same large PPTX file again using the configuration above and compare the result. Based on our internal tests with large PPTX files and similar hardware resources, the opening time should be significantly lower.

Regarding the .eml issue, please create a separate forum thread for that case, since .eml files are handled by a different viewer than PPT/PPTX files. The large difference you reported for such a small .eml file, where it opens in a few seconds locally but takes several minutes in production, suggests that there may also be an environment-specific issue involved affecting all the viewers, such as a PowerPoint or Email viewers. For example, this could be related to the server, network access, missing or different dependencies, antivirus scanning, or production configuration.

@gabriel.vega

Thanks for the response.

The file opening time has reduced significantly after applying the changes you suggested.

However, our current concern is regarding the search functionality. We disabled search by setting AllowSearch = false , and as a result, the files are now opening much faster. But the client requirement includes full search functionality within the documents.

Is there any way to keep search enabled while still maintaining the improved file opening performance we are currently getting?

We need to provide both:

  • Faster document opening performance
  • Search functionality as requested by the client

Any suggestions or recommended approach would be appreciated.

Thanks & Regards,
Mohit Tandel

@Mohit_Tandel

Thank you for sharing the additional details and the current configuration.

For PowerPoint files, we recommend managing the rendering resolution directly in the format-specific configuration, instead of relying only on the general DocOptions.ImageResolution.

In your case, please configure the ImageResolution inside PptConfig, especially for large PPT/PPTX files. This helps ensure that the PowerPoint renderer uses the intended resolution for that specific file type.

For example:

var config = new PptConfig
{
    DefaultRender = true,
    AllowSearch = true,
    ImageResolution = 72
};

var documentOptions = new DocOptions
{
    TimeOut = 600,
};

For better control and performance tuning, we recommend handling the image resolution independently for each document format. For example, PowerPoint, PDF, Word, Excel, and Email files may require different resolution settings depending on the document size, content complexity, and expected rendering quality.

For very large PowerPoint files, you can start testing with a lower resolution such as 72 DPI and then increase it gradually only if the output quality is not enough.

Also, please try enabling search in the PptConfig:

AllowSearch = true

This configuration may help improve the overall behavior when opening and processing PowerPoint files.

@gabriel.vega

Thank you for the suggestion.

We tested the configuration with AllowSearch = true inside PptConfig along with ImageResolution = 72.

However, once AllowSearch = true is enabled, the document opening time again increases to around 8–9 minutes for large PowerPoint files.

When AllowSearch = false, the same documents open much faster with acceptable performance.

Could you please suggest if there is any alternative approach or optimization available to keep search functionality enabled while avoiding this significant increase in loading time?

Thanks & Regards,
Mohit Tandel

@Mohit_Tandel,

When AllowSearch = true is enabled for PowerPoint files, Doconut uses the internal PDF-based rendering pipeline to extract searchable text and text coordinates. In this mode, the flow is:

PPT/PPTX file -> Internal PDF conversion -> PDF-based page rendering -> Rendered page images with search support

Because of this, the rendered page image resolution is controlled by PptConfig.PdfConfig.ImageResolution, not directly by PptConfig.ImageResolution. You can configure it like this:

config = new PptConfig
{
    DefaultRender = true,
    AllowSearch = true,
    PdfConfig = new PdfConfig
    {
        DefaultRender = true,

        // 72 is only an example value.
        // You can adjust this value to find the best balance
        // between image quality and rendering performance for your application.
        ImageResolution = 72
    }
};

Using a lower value, such as 72, or even 50 if lower image quality is acceptable, can reduce the size and rendering cost of the generated page images after the PowerPoint file is converted to PDF.

However, please note that this does not remove the initial delay. For large PowerPoint files, the most expensive step is still the full conversion from PowerPoint to PDF, which is required when search support is enabled.