2013-07-31 20 views
2

當使用VSTO 2012來操作MS Word文檔時,我發現文檔具有'WordOpenXML'字符串屬性,它是所有構成.docx包的文件將在將此Word文檔保存爲.docx時保存到磁盤。從'WordOpenXML'轉換爲內存中的System.IO.Packaging.Package

我想將此字符串轉換爲內存中等效的System.IO.Packaging.Package對象

SO question here非常相似。事實上,OP甚至在他的問題中提到了「記憶中」。但是,給出的答案涉及使用System.IO.Packaging.ZipPackage.Open方法將軟件包保存到磁盤。我不想將軟件包保存到磁盤,然後必須使用WordprocessingDocument.Open()方法再次打開它。相反,我希望一切都在內存中完成,而不涉及文件系統。

我看到WordprocessingDocument.Open()有一個需要Stream的重載。然而,我不確定我會如何從WordOpenXML字符串中準備這樣一個Stream,儘管我懷疑上面提到的帖子給出了很多答案。

回答

3

您可以使用此方法從WordOpenXml字符串內存流得到一個:

/// <summary> 
    /// Returns a System.IO.Packaging.Package stream for the given word open XML. 
    /// </summary> 
    /// <param name="wordOpenXML">The word open XML.</param> 
    /// <returns></returns> 
    public static MemoryStream GetPackageStreamFromWordOpenXML(string wordOpenXML) 
    { 
     XDocument doc = XDocument.Parse(wordOpenXML); 
     XNamespace pkg = 
      "http://schemas.microsoft.com/office/2006/xmlPackage"; 
     XNamespace rel = 
      "http://schemas.openxmlformats.org/package/2006/relationships"; 
     Package InmemoryPackage = null; 
     MemoryStream memStream = new MemoryStream(); 
     using (InmemoryPackage = Package.Open(memStream, FileMode.Create)) 
     { 
      // add all parts (but not relationships) 
      foreach (var xmlPart in doc.Root 
       .Elements() 
       .Where(p => 
        (string)p.Attribute(pkg + "contentType") != 
        "application/vnd.openxmlformats-package.relationships+xml")) 
      { 
       string name = (string)xmlPart.Attribute(pkg + "name"); 
       string contentType = (string)xmlPart.Attribute(pkg + "contentType"); 
       if (contentType.EndsWith("xml")) 
       { 
        Uri u = new Uri(name, UriKind.Relative); 
        PackagePart part = InmemoryPackage.CreatePart(u, contentType, 
         CompressionOption.SuperFast); 
        using (Stream str = part.GetStream(FileMode.Create)) 
        using (XmlWriter xmlWriter = XmlWriter.Create(str)) 
         xmlPart.Element(pkg + "xmlData") 
          .Elements() 
          .First() 
          .WriteTo(xmlWriter); 
       } 
       else 
       { 
        Uri u = new Uri(name, UriKind.Relative); 
        PackagePart part = InmemoryPackage.CreatePart(u, contentType, 
         CompressionOption.SuperFast); 
        using (Stream str = part.GetStream(FileMode.Create)) 
        using (BinaryWriter binaryWriter = new BinaryWriter(str)) 
        { 
         string base64StringInChunks = 
         (string)xmlPart.Element(pkg + "binaryData"); 
         char[] base64CharArray = base64StringInChunks 
          .Where(c => c != '\r' && c != '\n').ToArray(); 
         byte[] byteArray = 
          System.Convert.FromBase64CharArray(base64CharArray, 
          0, base64CharArray.Length); 
         binaryWriter.Write(byteArray); 
        } 
       } 
      } 
      foreach (var xmlPart in doc.Root.Elements()) 
      { 
       string name = (string)xmlPart.Attribute(pkg + "name"); 
       string contentType = (string)xmlPart.Attribute(pkg + "contentType"); 
       if (contentType == 
        "application/vnd.openxmlformats-package.relationships+xml") 
       { 
        // add the package level relationships 
        if (name == "/_rels/.rels") 
        { 
         foreach (XElement xmlRel in 
          xmlPart.Descendants(rel + "Relationship")) 
         { 
          string id = (string)xmlRel.Attribute("Id"); 
          string type = (string)xmlRel.Attribute("Type"); 
          string target = (string)xmlRel.Attribute("Target"); 
          string targetMode = 
           (string)xmlRel.Attribute("TargetMode"); 
          if (targetMode == "External") 
           InmemoryPackage.CreateRelationship(
            new Uri(target, UriKind.Absolute), 
            TargetMode.External, type, id); 
          else 
           InmemoryPackage.CreateRelationship(
            new Uri(target, UriKind.Relative), 
            TargetMode.Internal, type, id); 
         } 
        } 
        else 
        // add part level relationships 
        { 
         string directory = name.Substring(0, name.IndexOf("/_rels")); 
         string relsFilename = name.Substring(name.LastIndexOf('/')); 
         string filename = 
          relsFilename.Substring(0, relsFilename.IndexOf(".rels")); 
         PackagePart fromPart = InmemoryPackage.GetPart(
          new Uri(directory + filename, UriKind.Relative)); 
         foreach (XElement xmlRel in 
          xmlPart.Descendants(rel + "Relationship")) 
         { 
          string id = (string)xmlRel.Attribute("Id"); 
          string type = (string)xmlRel.Attribute("Type"); 
          string target = (string)xmlRel.Attribute("Target"); 
          string targetMode = 
           (string)xmlRel.Attribute("TargetMode"); 
          if (targetMode == "External") 
           fromPart.CreateRelationship(
            new Uri(target, UriKind.Absolute), 
            TargetMode.External, type, id); 
          else 
           fromPart.CreateRelationship(
            new Uri(target, UriKind.Relative), 
            TargetMode.Internal, type, id); 
         } 
        } 
       } 
      } 
      InmemoryPackage.Flush(); 
     } 
     return memStream; 
    } 
相關問題