.msg file with external resources viewing problem

Hi there!

Some of our customers are facing some problems while rendering msg files with your embedded viewer. They work on a limited intranet with no access to the external internet (due to security issues) and, on opening msg files with embedded resources pointing to the external (like a logo image) the viewer seems blocked until the request load fails with a 404 status.
Is there a way to replace all of this external images with a blanket or another solution?
We’re using html engine to view msg files and the latest version of the viewer…
As attachment you can find a test msg file!

Many thanks!

Gianluca

@gianboscolo,

Thanks for using GroupDocs.Viewer and sharing your concerns with us. In order to investigate the issue, we will require you to provide us following details.

  • Platform (.NET, Java, Cloud) of the API
  • Version of the API
  • Problematic/sample .msg file
  • Source code you are using to render the file

We shall be looking forward to your response.

Hi,

  • we’re using the .NET platform,
  • the version is the 17.6
  • i’m attaching the file to this post
  • the code on your github repository

Many thanks

GianlucaYour Apple Billing Invoice Number xxx.zip (17.4 KB)

Another solution i’m thinking about would be to reduce the timeout for the http calls… Can it be a solution?

Thank you

Gianluca

@gianboscolo,

Thanks for providing the details. We tested to render your provided .msg file with GroupDocs.Viewer for .NET 17.6.0 and the rendering results are as expected (see output). In case you are using any of our open source showcase applications hosted on GitHub, please mention its name. We shall be looking forward to your response.

As mentioned above, the problems raise when the user try to open the file from a machine not connected to the Internet: the viewer try (correctly) to load the external images but it causes a lot of time of waiting… Is there a way to remove this external images or to reduce the default timeout?

Thanks

@gianboscolo,

Thanks for coming back to us. In that case, you can set HtmlOptions.IsResourcesEmbedded to true. Using this setting, the API will embed all the resources, including CSS and images, into the body of HTML and you will not have to request for the resources. Hope this will solve your issue.

We tried also this but with no success… in the network tab, the call to the controller method get this
(more than 2 minutes…)

image.png (1.6 KB)

@gianboscolo,

Thanks for your response. From the details you have provided, it confirms that the issue is not related to the back end GroupDocs.Viewer API as rendering the provided document as HTML is taking no time in a console application. Instead, it is happening at the level of front-end application from where the request is sent for a particular page or resource. Multiple factors could be involved in this behavior of the application i.e. the size of the resource/content that is requested, network/DNS issue etc. You can use Fiddler to debug your web application. We would also like you to try our latest open source document viewer applications listed below.

We think that the problem can be reduced to network problems, but what i wanna do is to avoid to load external resources in the document to resolve the problem in this context. With process monitor we’ve seen that the same image is requested until 5 times and this, in the context of closed network, cause very large times of loading… Here the screen of process monitor (we cannot install fiddler or similar on the customer test machine)

Many thanks

image.png (3.1 KB)

@gianboscolo,

Thanks for your response.

As mentioned in the previous post, you can avoid loading external resources using HtmlOptions.IsResourcesEmbedded setting of GroupDocs.Viewer API. In that case, all the resources will be embedded inside the Html page. You can also try to create and test a simple web application that would render and display the documents in Html representation with embedded resources (as shown in below code sample). It may help you to figure out the issue in your environment.

// Create Html handler
ViewerHtmlHandler htmlHandler = new ViewerHtmlHandler(config);

string guid = DocumentName;

// Instantiate the HtmlOptions object
HtmlOptions options = new HtmlOptions();

// To get Html representation of pages with embedded resources
options.IsResourcesEmbedded = true;
            
// Get document pages in html form
List<PageHtml> pages = htmlHandler.GetPages(guid, options);

Hope it helps.

I’ve tried with this. This is the code:
image.png (5.1 KB)

and this is the result in the process monitor… the requests starts also with this paramether…
image.png (14.9 KB)

@gianboscolo,

Thanks for your response.

From the code snippet you shared, it seems that your front end application is based on ASP.NET_MVC_Front_End application. If yes, then you will have to set every occurrence of HtmlOptions.IsResourcesEmbedded to true and comment out the HtmlResourcePrefix property of HtmlOptions in ViewerController.cs. Furthermore, enclose the foreach loop in if (htmlOptions.IsResourcesEmbedded == false) condition in GetHtmlPages function as shown in the following code sample.

private List<PageHtml> GetHtmlPages(string filePath, HtmlOptions htmlOptions, out List<string> cssList)
        {
            var htmlPages = _htmlHandler.GetPages(filePath, htmlOptions);

            cssList = new List<string>();
            if (htmlOptions.IsResourcesEmbedded == false)
            {
                foreach (var page in htmlPages)
                {


                    var test = page.HtmlResources;
                    var indexOfBodyOpenTag = page.HtmlContent.IndexOf("<body>", StringComparison.InvariantCultureIgnoreCase);
                    if (indexOfBodyOpenTag > 0)
                        page.HtmlContent = page.HtmlContent.Substring(indexOfBodyOpenTag + "<body>".Length);

                    var indexOfBodyCloseTag = page.HtmlContent.IndexOf("</body>", StringComparison.InvariantCultureIgnoreCase);
                    if (indexOfBodyCloseTag > 0)
                        page.HtmlContent = page.HtmlContent.Substring(0, indexOfBodyCloseTag);
                    if (Path.GetExtension(filePath) == ".msg")
                    {

                        foreach (var resource in page.HtmlResources.Where(_ => _.ResourceType == HtmlResourceType.Image))
                        {
                            string imagePath = string.Format("resources\\page{0}\\{1}",
                                page.PageNumber, resource.ResourceName);

                            page.HtmlContent = page.HtmlContent.Replace(resource.ResourceName,
                                string.Format("/document-viewer/GetResourceForHtml?documentPath={0}&pageNumber={1}&resourceName={2}",
                                filePath, page.PageNumber, resource.ResourceName));
                        }
                    }
                    foreach (var resource in page.HtmlResources.Where(_ => _.ResourceType == HtmlResourceType.Style))
                    {
                        var cssStream = _htmlHandler.GetResource(filePath, resource);
                        var text = new StreamReader(cssStream).ReadToEnd();

                        var needResave = false;
                        if (text.IndexOf("url(\"", StringComparison.Ordinal) >= 0 &&
                            text.IndexOf("url(\"/document-viewer/GetResourceForHtml?documentPath=", StringComparison.Ordinal) < 0)
                        {
                            needResave = true;
                            text = text.Replace("url(\"",
                            string.Format("url(\"/document-viewer/GetResourceForHtml?documentPath={0}&pageNumber={1}&resourceName=",
                            filePath, page.PageNumber));
                        }

                        if (text.IndexOf("url('", StringComparison.Ordinal) >= 0 &&
                            text.IndexOf("url('/document-viewer/GetResourceForHtml?documentPath=", StringComparison.Ordinal) < 0)
                        {
                            needResave = true;
                            text = text.Replace("url('",
                                string.Format(
                                    "url('/document-viewer/GetResourceForHtml?documentPath={0}&pageNumber={1}&resourceName=",
                                    filePath, page.PageNumber));
                        }
                        // update path to image resource


                        cssList.Add(text);

                        if (needResave)
                        {
                            var fullPath = Path.Combine(_tempPath, filePath.Replace('.', '_'), "html", "resources",
                                string.Format("page{0}", page.PageNumber), resource.ResourceName);

                            System.IO.File.WriteAllText(fullPath, text);
                        }
                    }

                    List<string> cssClasses = Utils.GetCssClasses(page.HtmlContent);
                    foreach (var cssClass in cssClasses)
                    {
                        var newCssClass = string.Format("page-{0}-{1}", page.PageNumber, cssClass);

                        page.HtmlContent = page.HtmlContent.Replace(cssClass, newCssClass);
                        for (int i = 0; i < cssList.Count; i++)
                            cssList[i] = cssList[i].Replace(cssClass, newCssClass);
                    }
                }
            }
            return htmlPages;
        }

It will embed the resources into the Html content of the page and the application will not request for resources externally. Hope it helps.