如何使用字节流形成Word文档

时间:2011-08-14 12:39:48

标签: c# ms-word

我有一个字节流,实际上(如果正确)将形成一个有效的Word文件,我需要将此流转换为Word文件而不将其写入磁盘,我从SQL Server数据库表中获取原始流:

ID   Name    FileData
----------------------------------------
1    Word1   292jf2jf2ofm29fj29fj29fj29f2jf29efj29fj2f9 (actual file data)

FileData字段包含数据。

Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document(); 
doc = word.Documents.Open(@"C:\SampleText.doc");
doc.Activate();

以上代码打开并填写文件系统中的Word文件,我不希望这样,我想定义一个新的Microsoft.Office.Interop.Word.Document,但我想从字节流中手动填充其内容。

获取内存中的Word文档后,我想对关键字进行一些解析。

有什么想法吗?

4 个答案:

答案 0 :(得分:0)

  1. 创建一个内存文件系统,有驱动程序。
  2. 给出一个指向ftp服务器路径(或其他东西)的路径,然后用它来推送数据。
  3. 需要注意的一件重要事项:在数据库中存储文件通常不是一个好设计。

答案 1 :(得分:0)

可能没有任何直截了当的方法。我找到了几个搜索它的解决方案:

我不知道这是否适合您,但显然API并未提供您所追求的(不幸的是)。

答案 2 :(得分:0)

你可以看看Sharepoint如何解决这个问题。他们为存储在数据库中的文档创建了一个Web界面。

在您的应用程序中创建或嵌入可以向Word提供页面的Web服务器并不难。您甚至不必使用标准端口。

答案 3 :(得分:0)

实际上只有两种方法可以以编程方式打开Word文档-作为物理文件或作为流。有一个“包”,但这并不真正适用。

此处介绍了流方法:https://docs.microsoft.com/en-us/office/open-xml/how-to-open-a-word-processing-document-from-a-stream

但即使它依赖于存在物理文件才能形成流:

string strDoc = @"C:\Users\Public\Public Documents\Word13.docx";
Stream stream = File.Open(strDoc, FileMode.Open);

我能提供的最佳解决方案是将文件写到临时位置,应用程序的服务帐户有权写该临时位置:

string newDocument = @"C:\temp\test.docx";
WriteFile(byteArray, newDocument);

如果在我的示例中没有对“ temp”文件夹的权限,则只需添加应用程序的服务帐户(应用程序池,如果是网站)即可完全控制该文件夹。

您将使用此WriteFile()函数:

/// <summary>
/// Write a byte[] to a new file at the location where you choose
/// </summary>
/// <param name="byteArray">byte[] that consists of file data</param>
/// <param name="newDocument">Path to where the new document will be written</param>
public static void WriteFile(byte[] byteArray, string newDocument)
{
    using (MemoryStream stream = new MemoryStream())
    {
        stream.Write(byteArray, 0, (int)byteArray.Length);

        // Save the file with the new name
        File.WriteAllBytes(newDocument, stream.ToArray());
    }
}

从那里,您可以使用OpenXML打开它并编辑文件。无法将字节[]格式的Word文档直接打开到Word实例(Interop,OpenXML或其他方式)中,因为您需要documentPath,或者前面提到的依赖于物理的流方法文件。您可以通过将字节读取为字符串,然后将其读取为XML,来编辑将获得的字节,或者直接编辑字符串:

string docText = null;
byte[] byteArray = null;
using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentPath, true))
{
    using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
    {
        docText = sr.ReadToEnd();  // <-- converts byte[] stream to string
    }

    // Play with the XML
    XmlDocument xml = new XmlDocument();
    xml.LoadXml(docText);  // the string contains the XML of the Word document

    XmlNodeList nodes = xml.GetElementsByTagName("w:body");
    XmlNode chiefBodyNode = nodes[0];
    // add paragraphs with AppendChild... 
    // remove a node by getting a ChildNode and removing it, like this...
    XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
    chiefBodyNode.RemoveChild(firstParagraph);

    // Or play with the string form
    docText = docText.Replace("John","Joe");

    // If you manipulated the XML, write it back to the string
    //docText = xml.OuterXml;  // comment out the line above if XML edits are all you want to do, and uncomment out this line

     // Save the file - yes, back to the file system - required
     using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
     {                    
        sw.Write(docText);
     }
 }

 // Read it back in as bytes
 byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving

参考:

https://docs.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part

我知道这不是理想的选择,但是我进行了搜索,但没有找到一种直接编辑byte[]的方法,而无需进行转换,该转换涉及写出文件,在Word中打开进行编辑,然后实质上重新上传它恢复新的字节。与我尝试过的其他byte[] byteArray = Encoding.UTF8.GetBytes(docText);EncodingUTF7Default,{{1 }}),这是我在上面的最后一行中尝试使用我的Unicode函数将其写回时发现的。如果不进行编码,而只是使用ASCII进行收集,然后使用WriteFile()将字节写回,则可以正常工作。

更新

可能可以这样操作字节:

File.ReadAllBytes()

参考:

https://docs.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)

但是请注意,即使此方法也需要保存文档,然后将其读回,以将其保存到数据库的字节中。如果文档的格式为WriteFile(),而不是打开文档所在行的//byte[] byteArray = File.ReadAllBytes("Test.docx"); // you might be able to assign your bytes here, instead of from a file? byte[] byteArray = GetByteArrayFromDatabase(fileId); // function you have for getting the document from the database using (MemoryStream mem = new MemoryStream()) { mem.Write(byteArray, 0, (int)byteArray.Length); using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true)) { // do your updates -- see string or XML edits, above // Once done, you may need to save the changes.... //wordDoc.MainDocumentPart.Document.Save(); } // But you will still need to save it to the file system here.... // You would update "documentPath" to a new name first... string documentPath = @"C:\temp\newDoc.docx"; using (FileStream fileStream = new FileStream(documentPath, System.IO.FileMode.CreateNew)) { mem.WriteTo(fileStream); } } // And then read the bytes back in, to save it to the database byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving ,也会失败。

如果您不在.doc块之外但仍在{{1内,则可以直接使用内存流并将其保存回字节中,而不是将文件保存到文件系统中的最后一部分。 }}语句:

.docx

这将有您的Word文档WordprocessingDocument.Open()