{"id":1961,"date":"2016-02-03T15:21:05","date_gmt":"2016-02-03T15:21:05","guid":{"rendered":"http:\/\/www.ericwhite.com\/home2\/bm8qcmjy\/public_html\/blog\/?page_id=1961"},"modified":"2016-03-18T10:28:27","modified_gmt":"2016-03-18T10:28:27","slug":"building-an-asp-net-web-application-that-displays-docx-as-html","status":"publish","type":"page","link":"https:\/\/www.ericwhite.com\/blog\/building-an-asp-net-web-application-that-displays-docx-as-html\/","title":{"rendered":"Building an ASP.NET Web Application that Displays DOCX as HTML"},"content":{"rendered":"<p><span class=\"Back\"><a class=\"Back\" href=\"https:\/\/www.ericwhite.com\/blog\/wmltohtmlconverter-developer-center\/\">Return to the<br \/>WmlToHtmlConverter<br \/>Developer Center<\/a><\/span>There are four basic operations that developers need to do when building an ASP.NET Web application with Open XML functionality:<\/p>\n<ul>\n<li>Upload a document<\/li>\n<li>Modify the document using the Open XML SDK<\/li>\n<li>Convert the document to HTML\/CSS and display the converted HTML<\/li>\n<li>Download the modified document<\/li>\n<\/ul>\n<p>In this screen-cast, I demonstrate how to start from nothing and build such an application using Visual Studio 2013. &nbsp;Note that there is nothing about this application that is specific to VS 2013. &nbsp;The approach and the code will work as well with VS 2012 &nbsp;or 2010. &nbsp;Below the screen-cast, I list the interesting code so that it is as easy as possible for you to cut and paste the code and build your own similar application.<\/p>\n<p><iframe loading=\"lazy\" title=\"ASP NET Display DOCX\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/Ygr6Sq5IRiA?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe><\/p>\n<p>Here is the source for the Web form:<\/p>\n<p><pre class=\"prettyprint\">&lt;%@ Page Language=&quot;C#&quot; AutoEventWireup=&quot;true&quot; CodeBehind=&quot;WebForm1.aspx.cs&quot; Inherits=&quot;WebApplication1.WebForm1&quot; %&gt;\r\n\r\n&lt;!DOCTYPE html&gt;\r\n\r\n&lt;html xmlns=&quot;http:\/\/www.w3.org\/1999\/xhtml&quot;&gt;\r\n&lt;head runat=&quot;server&quot;&gt;\r\n    &lt;title&gt;&lt;\/title&gt;\r\n&lt;\/head&gt;\r\n&lt;body&gt;\r\n    &lt;form id=&quot;form1&quot; runat=&quot;server&quot;&gt;\r\n    &lt;div&gt;\r\n        &lt;asp:FileUpload ID=&quot;FileUploadControl&quot; runat=&quot;server&quot; \/&gt;\r\n        &lt;p style=&quot;line-height: .5em;&quot; \/&gt;\r\n        &lt;asp:Label ID=&quot;lblMessage&quot; runat=&quot;server&quot; Text=&quot;&quot;&gt;&lt;\/asp:Label&gt;\r\n        &lt;p style=&quot;line-height: .5em;&quot; \/&gt;\r\n        &lt;asp:Button ID=&quot;btnUpload&quot; runat=&quot;server&quot; Text=&quot;Upload&quot; OnClick=&quot;btnUpload_Click&quot; \/&gt;\r\n        &lt;p style=&quot;line-height: .5em;&quot; \/&gt;\r\n        &lt;asp:Button ID=&quot;btnModify&quot; runat=&quot;server&quot; Text=&quot;Modify&quot; OnClick=&quot;btnModify_Click&quot; \/&gt;\r\n        &lt;p style=&quot;line-height: .5em;&quot; \/&gt;\r\n        &lt;asp:Button ID=&quot;btnDisplay&quot; runat=&quot;server&quot; Text=&quot;Display&quot; OnClick=&quot;btnDisplay_Click&quot; \/&gt;\r\n        &lt;p style=&quot;line-height: .5em;&quot; \/&gt;\r\n        &lt;asp:Button ID=&quot;btnDownload&quot; runat=&quot;server&quot; Text=&quot;Download&quot; OnClick=&quot;btnDownload_Click&quot; \/&gt;\r\n    &lt;\/div&gt;\r\n    &lt;\/form&gt;\r\n&lt;lt;\/body&gt;\r\n&lt;\/html&gt;<\/pre>\n<\/p>\n<p>Here is the listing, in its entirety, for the code behind the Web page:&nbsp;<\/p>\n<p><pre class=\"prettyprint\">using System;\r\nusing System.Collections.Generic;\r\nusing System.Drawing.Imaging;\r\nusing System.IO;\r\nusing System.Linq;\r\nusing System.Text;\r\nusing System.Web;\r\nusing System.Web.UI;\r\nusing System.Web.UI.WebControls;\r\nusing System.Xml.Linq;\r\nusing DocumentFormat.OpenXml.Packaging;\r\nusing DocumentFormat.OpenXml.Wordprocessing;\r\nusing OpenXmlPowerTools;\r\n\r\nnamespace WebApplication1\r\n{\r\n    public partial class WebForm1 : System.Web.UI.Page\r\n    {\r\n        protected void Page_Load(object sender, EventArgs e)\r\n        {\r\n\r\n        }\r\n\r\n        protected void btnUpload_Click(object sender, EventArgs e)\r\n        {\r\n            if (FileUploadControl.HasFile)\r\n                try\r\n                {\r\n                    string fileNameFromUser = FileUploadControl.FileName;\r\n\r\n                    var fiFileName = new FileInfo(fileNameFromUser);\r\n                    if (Util.IsWordprocessingML(fiFileName.Extension))\r\n                    {\r\n                        using (MemoryStream memoryStream = new MemoryStream())\r\n                        {\r\n                            memoryStream.Write(FileUploadControl.FileBytes, 0,\r\n                                FileUploadControl.FileBytes.Length);\r\n\r\n                            \/\/ Open and close the WordprocessingML document to make sure\r\n                            \/\/ that the SDK can open it.\r\n                            using (WordprocessingDocument wDoc =\r\n                                WordprocessingDocument.Open(memoryStream, true))\r\n                            {\r\n                            }\r\n                            lblMessage.Text = &quot;File uploaded successfully&quot;;\r\n                            Session[&quot;ByteArray&quot;] = FileUploadControl.FileBytes;\r\n                            Session[&quot;FileNameFromUser&quot;] = fileNameFromUser;\r\n                        }\r\n                    }\r\n                    else\r\n                    {\r\n                        lblMessage.Text = &quot;ERROR: Not a WordprocessingML document&quot;;\r\n                        Session[&quot;ByteArray&quot;] = null;\r\n                        Session[&quot;FileNameFromUser&quot;] = null;\r\n                    }\r\n                }\r\n                catch (Exception ex)\r\n                {\r\n                    lblMessage.Text = &quot;ERROR: &quot; + ex.Message.ToString();\r\n                    Session[&quot;ByteArray&quot;] = null;\r\n                    Session[&quot;FileNameFromUser&quot;] = null;\r\n                }\r\n            else\r\n            {\r\n                lblMessage.Text = &quot;You have not specified a file.&quot;;\r\n                Session[&quot;ByteArray&quot;] = null;\r\n                Session[&quot;FileNameFromUser&quot;] = null;\r\n            }\r\n        }\r\n\r\n        protected void btnModify_Click(object sender, EventArgs e)\r\n        {\r\n            byte[] byteArray = (byte[])(Session[&quot;ByteArray&quot;]);\r\n            if (byteArray != null)\r\n            {\r\n                try\r\n                {\r\n\r\n                    using (MemoryStream memoryStream = new MemoryStream())\r\n                    {\r\n                        memoryStream.Write(byteArray, 0, byteArray.Length);\r\n                        using (WordprocessingDocument wDoc =\r\n                            WordprocessingDocument.Open(memoryStream, true))\r\n                        {\r\n                            var body = wDoc.MainDocumentPart.Document.Body;\r\n                            var lastPara = body.Elements&lt;Paragraph&gt;().LastOrDefault();\r\n                            var newPara = new Paragraph(\r\n                                new Run(\r\n                                    new Text(&quot;Hello World!&quot;)));\r\n                            lastPara.InsertAfterSelf(newPara);\r\n                        }\r\n                        Session[&quot;ByteArray&quot;] = memoryStream.ToArray();\r\n                        lblMessage.Text = &quot;Paragraph added to DOCX&quot;;\r\n                    }\r\n                }\r\n                catch (Exception ex)\r\n                {\r\n                    lblMessage.Text = &quot;ERROR: &quot;quot; + ex.Message.ToString();\r\n                }\r\n            }\r\n            else\r\n            {\r\n                lblMessage.Text = &quot;You have not specified a file.&quot;;\r\n            }\r\n        }\r\n\r\n        static string DocxConvertedToHtmlDirectory = &quot;DocxConvertedToHtml\/&quot;;\r\n\r\n        protected void btnDisplay_Click(object sender, EventArgs e)\r\n        {\r\n            byte[] byteArray = (byte[])(Session[&quot;ByteArray&quot;]);\r\n\r\n            if (byteArray != null)\r\n            {\r\n                try\r\n                {\r\n                    DirectoryInfo convertedDocsDirectory =\r\n                        new DirectoryInfo(Server.MapPath(DocxConvertedToHtmlDirectory));\r\n                    if (!convertedDocsDirectory.Exists)\r\n                        convertedDocsDirectory.Create();\r\n                    Guid g = Guid.NewGuid();\r\n                    var htmlFileName = g.ToString() + &quot;.html&quot;;\r\n                    ConvertToHtml(byteArray, convertedDocsDirectory, htmlFileName);\r\n                    Response.Redirect(DocxConvertedToHtmlDirectory + htmlFileName);\r\n                }\r\n                catch (Exception ex)\r\n                {\r\n                    lblMessage.Text = &quot;ERROR: &quot; + ex.Message.ToString();\r\n                }\r\n            }\r\n            else\r\n            {\r\n                lblMessage.Text = &quot;You have not specified a file.&quot;;\r\n            }\r\n        }\r\n\r\n        public static void ConvertToHtml(byte[] byteArray, DirectoryInfo destDirectory, string htmlFileName)\r\n        {\r\n            FileInfo fiHtml = new FileInfo(Path.Combine(destDirectory.FullName, htmlFileName));\r\n            using (MemoryStream memoryStream = new MemoryStream())\r\n            {\r\n                memoryStream.Write(byteArray, 0, byteArray.Length);\r\n                using (WordprocessingDocument wDoc = WordprocessingDocument.Open(memoryStream, true))\r\n                {\r\n                    var imageDirectoryFullName =\r\n                        fiHtml.FullName.Substring(0, fiHtml.FullName.Length - fiHtml.Extension.Length) + &quot;_files&quot;;\r\n                    var imageDirectoryRelativeName =\r\n                        fiHtml.Name.Substring(0, fiHtml.Name.Length - fiHtml.Extension.Length) + &quot;_files&quot;;\r\n                    int imageCounter = 0;\r\n                    var pageTitle = (string)wDoc\r\n                        .CoreFilePropertiesPart\r\n                        .GetXDocument()\r\n                        .Descendants(DC.title)\r\n                        .FirstOrDefault();\r\n\r\n                    HtmlConverterSettings settings = new HtmlConverterSettings()\r\n                    {\r\n                        PageTitle = pageTitle,\r\n                        FabricateCssClasses = true,\r\n                        CssClassPrefix = &quot;pt-&quot;,\r\n                        RestrictToSupportedLanguages = false,\r\n                        RestrictToSupportedNumberingFormats = false,\r\n                        ImageHandler = imageInfo =&gt;\r\n                        {\r\n                            DirectoryInfo localDirInfo = new DirectoryInfo(imageDirectoryFullName);\r\n                            if (!localDirInfo.Exists)\r\n                                localDirInfo.Create();\r\n                            ++imageCounter;\r\n                            string extension = imageInfo.ContentType.Split(&#39;\/&#39;)[1].ToLower();\r\n                            ImageFormat imageFormat = null;\r\n                            if (extension == &quot;png&quot;)\r\n                            {\r\n                                \/\/ Convert png to jpeg.\r\n                                extension = &quot;gif&quot;;\r\n                                imageFormat = ImageFormat.Gif;\r\n                            }\r\n                            else if (extension == &quot;gif&quot;)\r\n                                imageFormat = ImageFormat.Gif;\r\n                            else if (extension == &quot;bmp&quot;)\r\n                                imageFormat = ImageFormat.Bmp;\r\n                            else if (extension == &quot;jpeg&quot;)\r\n                                imageFormat = ImageFormat.Jpeg;\r\n                            else if (extension == &quot;tiff&quot;)\r\n                            {\r\n                                \/\/ Convert tiff to gif.\r\n                                extension = &quot;gif&quot;;\r\n                                imageFormat = ImageFormat.Gif;\r\n                            }\r\n                            else if (extension == &quot;x-wmf&quot;)\r\n                            {\r\n                                extension = &quot;wmf&quot;;\r\n                                imageFormat = ImageFormat.Wmf;\r\n                            }\r\n\r\n                            \/\/ If the image format isn&#39;t one that we expect, ignore it,\r\n                            \/\/ and don&#39;t return markup for the link.\r\n                            if (imageFormat == null)\r\n                                return null;\r\n\r\n                            FileInfo imageFileName = new FileInfo(imageDirectoryFullName + &quot;\/image&quot; +\r\n                                imageCounter.ToString() + &quot;.&quot; + extension);\r\n                            try\r\n                            {\r\n                                imageInfo.Bitmap.Save(imageFileName.FullName, imageFormat);\r\n                            }\r\n                            catch (System.Runtime.InteropServices.ExternalException)\r\n                            {\r\n                                return null;\r\n                            }\r\n                            XElement img = new XElement(Xhtml.img,\r\n                                new XAttribute(NoNamespace.src, imageDirectoryRelativeName + &quot;\/&quot; + imageFileName.Name),\r\n                                imageInfo.ImgStyleAttribute,\r\n                                imageInfo.AltText != null ?\r\n                                    new XAttribute(NoNamespace.alt, imageInfo.AltText) : null);\r\n                            return img;\r\n                        }\r\n                    };\r\n                    XElement html = HtmlConverter.ConvertToHtml(wDoc, settings);\r\n\r\n                    \/\/ Note: the xhtml returned by ConvertToHtmlTransform contains objects of type\r\n                    \/\/ XEntity.  PtOpenXmlUtil.cs define the XEntity class.  See\r\n                    \/\/ http:\/\/blogs.msdn.com\/ericwhite\/archive\/2010\/01\/21\/writing-entity-references-using-linq-to-xml.aspx\r\n                    \/\/ for detailed explanation.\r\n                    \/\/\r\n                    \/\/ If you further transform the XML tree returned by ConvertToHtmlTransform, you\r\n                    \/\/ must do it correctly, or entities will not be serialized properly.\r\n\r\n                    var body = html.Descendants(Xhtml.body).First();\r\n                    body.AddFirst(\r\n                        new XElement(Xhtml.p,\r\n                            new XElement(Xhtml.A,\r\n                                new XAttribute(&quot;href&quot;, &quot;\/WebForm1.aspx&quot;), &quot;Go back to Upload Page&quot;)));\r\n\r\n                    var htmlString = html.ToString(SaveOptions.DisableFormatting);\r\n\r\n                    File.WriteAllText(fiHtml.FullName, htmlString, Encoding.UTF8);\r\n                }\r\n            }\r\n        }\r\n\r\n        protected void btnDownload_Click(object sender, EventArgs e)\r\n        {\r\n            byte[] byteArray = (byte[])(Session[&quot;ByteArray&quot;]);\r\n\r\n            if (byteArray != null)\r\n            {\r\n                Response.Clear();\r\n                Response.ContentType = &quot;application\/octet-stream&quot;;\r\n                string fileName = (string)(Session[&quot;FileNameFromUser&quot;]);\r\n                Response.AddHeader(&quot;Content-Disposition&quot;,\r\n                    String.Format(&quot;attachment; filename={0}&quot;, fileName));\r\n                Response.BinaryWrite(byteArray);\r\n                Response.Flush();\r\n                Response.End();\r\n            }\r\n            else\r\n            {\r\n                lblMessage.Text = &quot;You have not specified a file.&quot;;\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n<p>Cheers, Eric<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Return to theWmlToHtmlConverterDeveloper CenterThere are four basic operations that developers need to do when building an ASP.NET Web application with Open XML functionality: Upload a document Modify the document using the Open XML SDK Convert the document to HTML\/CSS and display the converted HTML Download the modified document In this screen-cast, I demonstrate how to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_bbp_topic_count":0,"_bbp_reply_count":0,"_bbp_total_topic_count":0,"_bbp_total_reply_count":0,"_bbp_voice_count":0,"_bbp_anonymous_reply_count":0,"_bbp_topic_count_hidden":0,"_bbp_reply_count_hidden":0,"_bbp_forum_subforum_count":0,"_s2mail":"","footnotes":""},"class_list":["post-1961","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages\/1961","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/comments?post=1961"}],"version-history":[{"count":4,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages\/1961\/revisions"}],"predecessor-version":[{"id":2630,"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/pages\/1961\/revisions\/2630"}],"wp:attachment":[{"href":"https:\/\/www.ericwhite.com\/blog\/wp-json\/wp\/v2\/media?parent=1961"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}