Docx viewer for the site

  1. I have a Web API project. Is there any docx viewer for the site? from nuget, for example. I didn't find any free ones.

  2. If not, how can I convert docx to pdf(provided that office is not installed on the computer). Tried using using Microsoft.Office.Interop.Word;, but it doesn't work without MS Office.

Author: endovitskiiy, 2016-12-01

3 answers

I will offer a not very perfect version of "handles" via xslt. Among the disadvantages - you need to suffer with the tables, it is possible to tinker with the auto-numbering of lists. There are three "modules": xslt script (save as docx.xslt), cs conversion, and js numbering edit.

<?xml version="1.0"?>
<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">

<xsl:template match="/">
<xsl:for-each select="/w:document/w:body/*">
<xsl:apply-templates select="." mode="a1" />


<xsl:if test="name(.)='w:tbl'">
  <table border="0" cellpadding="0" cellspacing="0" style="padding:0;margin:0;">
  <xsl:for-each select="w:tr"> <tr>
    <xsl:for-each select="w:tc"> <td>
      <xsl:value-of select="concat('&lt;td style=','')" disable-output-escaping="yes"/>
      <xsl:value-of select="concat('&gt;','')" disable-output-escaping="yes"/>   
      <xsl:for-each select="*/w:tcBorders/*"><!-- xsl:if test="@w:val != 'nil'">border-<xsl:value-of select="replace(name(.),'w:','')"/>:solid;</xsl:if --></xsl:for-each>

       <xsl:for-each select="*/*/w:t">
         <xsl:value-of select="node()"/>
       </xsl:for-each></td>
  </xsl:for-each></tr>
  </xsl:for-each>
  </table>
</xsl:if>
</xsl:for-each></xsl:template>

<xsl:template match="*" mode="a1">

<xsl:if test="name(.) = 'w:p'">    
   <xsl:value-of select="concat('&lt;div style=','')" disable-output-escaping="yes"/>
</xsl:if>
<xsl:if test="name(.) != 'w:p'">
   <xsl:value-of select="concat('&lt;span style=','')" disable-output-escaping="yes"/>
</xsl:if>
<xsl:for-each select="w:pPr">
<xsl:for-each select="w:jc[@w:val ='center']" >text-align:center;</xsl:for-each>
<xsl:for-each select="w:rPr">
  <xsl:for-each select="w:b" >font-weight:bold;</xsl:for-each>
  <xsl:for-each select="w:i" >font-style:italic;</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
<xsl:value-of select="concat('>','')" disable-output-escaping="yes"/>
<xsl:for-each select="w:pPr/w:numPr"><xsl:value-of select="concat('&lt;span id=num','')" disable-output-escaping="yes"/><xsl:number format="1" count="w:numPr" level="any" /> i=<xsl:value-of select="w:ilvl/@w:val"/> n=<xsl:value-of select="w:numId/@w:val"/><xsl:value-of select="concat('&gt;&lt;/span&gt;','')" disable-output-escaping="yes"/></xsl:for-each>
<xsl:for-each select="w:t"><xsl:value-of select="node()"/></xsl:for-each> 
<xsl:if test="name(.) = 'w:p'"> 
   <xsl:for-each select="w:r"><xsl:apply-templates select="." mode="a1" /></xsl:for-each>
   <xsl:value-of select="concat('&lt;/div&gt;','')" disable-output-escaping="yes"/>
</xsl:if>
<xsl:if test="name(.) != 'w:p'">
   <xsl:value-of select="concat('&lt;/span&gt;','')" disable-output-escaping="yes"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

The c# code itself (pure unpacking + xslt conversion)

    public static string docx2html(string filename) {
        using (MemoryStream stm = new MemoryStream())
        using (Stream f = File.OpenRead(filename)) {
            docx2html(f, stm);
            return System.Text.UTF8Encoding.UTF8.GetString(stm.ToArray());
          }

       }

    public static void docx2html(Stream file, Stream dest) {
        int ready = 0; while (ready++ < 10){ /*защита от повисания, обход архива*/
            byte[] head = new byte[30]; file.Read(head, 0, 30); if (head[0] != 'P') break;  //zip-header
            int i = (head[27] + head[29]) * 256 + head[28]; //  extra len
            long paked = BitConverter.ToInt32(head,18);
            byte[] nam = new byte[255];
            file.Read(nam, 0, head[26]);
            if (i != 0) file.Seek(i, SeekOrigin.Current);
            String aname = System.Text.Encoding.ASCII.GetString(nam, 0, head[26]);
            if (aname == "word/document.xml"){
                long lastpos = file.Position;
                using (System.IO.Compression.DeflateStream deflate = new System.IO.Compression.DeflateStream(file, System.IO.Compression.CompressionMode.Decompress)){                        
                    System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
                    trans.Load( System.Web.HttpContext.Current.Server.
                      MapPath("docx.xml")); /*Шаблон, который выше*/
                    trans.Transform(System.Xml.XmlReader.Create(deflate), new System.Xml.Xsl.XsltArgumentList(), dest);                        
                    return;
                }                                        
                file.Position = lastpos + paked;
            }else file.Seek(paked, SeekOrigin.Current);
        };                

       }

And if necessary, edit numbered lists:

var i=1;
/*Правка результата выборки*/
var num, j,n;
var num_lv1 = 0;
var num_lv2 = 0;
while (num=document.getElementById("num"+i)) { /*Правка автонумерация*/
   j = parseInt(num.attributes['i'].value);
   n = parseInt(num.attributes['n'].value);
   switch (n){
     case 1: num.innerHTML = "<br/>"+(++num_lv1) + " "; num_lv2=0; break;
     case 5: num.innerHTML = "- " ; break;
     case 4: break;
     case 6: if (j==0)  { if (num.parentElement.outerHTML.length < 60) break; /*Фейки???*/
          num.innerHTML = "<br/>"+ (++num_lv1) + " ";  num_lv2=0; break;};
     case 3:;
     case 2: num.innerHTML = num_lv1 + "."  + (++num_lv2)+" "; break;
     default: num.innerHTML = "["+j + "." + n + "]";
     }
  //num.innerHTML += "["+j + "." + n + "]";
   var xx=  num.nextSibling;
    if ((xx)&&(xx.tagName=="SPAN")) {       
      num.style.fontWeight =  xx.style.fontWeight;
      }

   i++;
   }

If anyone has a better option, I will be happy. With the list on xslt, I couldn't think of how make the numbering. Plus, the tables are muddy.

P.S If you need to convert to text, you can use a simpler query

<?xml version=""1.0""?><xsl:stylesheet xmlns:xsl=""http://www.w3.org/TR/WD-xsl"">
<xsl:template match=""/"">
<xsl:for-each select=""/w:document/w:body/w:p"">&#13;<xsl:for-each select=""w:r/w:t"">
<xsl:value-of select=""node()""/></xsl:for-each></xsl:for-each>
</xsl:templ‌​ate></xsl:stylesheet‌​>
 2
Author: nick_n_a, 2017-06-09 11:21:42

There is such a service from Microsoft: View Office documents online.

 0
Author: Alexander Petrov, 2016-12-02 06:54:29

I apologize that I answer without going into the question, but most likely it is possible using the Google Docs / Drive API. (I did not check it, but logic suggests that there is such a possibility)

Https://developers.google.com/drive/v2/reference/

In addition there are ASP.NET Document Viewer - for displaying PDF, Word, Excel & other formats

Https://code.msdn.microsoft.com/ASPNET-Document-Viewer-e7c2a39f

 0
Author: Andrew, 2017-06-09 13:03:30