只有两种编程方式可以打开 Word 文档——作为物理文件或流。有“包装”,但实际上并不适用。
这里介绍了流方法:
https://learn.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()
函数:
public static void WriteFile(byte[] byteArray, string newDocument)
{
using (MemoryStream stream = new MemoryStream())
{
stream.Write(byteArray, 0, (int)byteArray.Length);
File.WriteAllBytes(newDocument, stream.ToArray());
}
}
从那里,您可以使用OpenXML打开并编辑文件。没有办法直接将Word文档以byte[]形式打开到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();
}
XmlDocument xml = new XmlDocument();
xml.LoadXml(docText);
XmlNodeList nodes = xml.GetElementsByTagName("w:body");
XmlNode chiefBodyNode = nodes[0];
XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
chiefBodyNode.RemoveChild(firstParagraph);
docText = docText.Replace("John","Joe");
using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
{
sw.Write(docText);
}
}
byteArray = File.ReadAllBytes(documentPath);
参考:
https://learn.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);
会破坏它们,任何其他我尝试过的Encoding
(UTF7
、Default
、Unicode
、ASCII
)也是如此,当我尝试使用上面的WriteFile()
函数将它们写回时,在最后一行。当未编码并仅使用File.ReadAllBytes()
收集,然后使用WriteFile()
将字节写回时,它可以正常工作。
更新:
可能可以像这样操作字节:
byte[] byteArray = GetByteArrayFromDatabase(fileId);
using (MemoryStream mem = new MemoryStream())
{
mem.Write(byteArray, 0, (int)byteArray.Length);
using (WordprocessingDocument wordDoc =
WordprocessingDocument.Open(mem, true))
{
}
string documentPath = @"C:\temp\newDoc.docx";
using (FileStream fileStream = new FileStream(documentPath,
System.IO.FileMode.CreateNew))
{
mem.WriteTo(fileStream);
}
}
byteArray = File.ReadAllBytes(documentPath);
参考:
https://learn.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)
但请注意,即使使用此方法也需要保存文档,然后重新读取它,以便将其保存为数据库的字节。如果文档在打开文档的那一行中是.doc
格式而不是.docx
,则此方法也会失败。
除了最后一个部分将文件保存到文件系统之外,您还可以将内存流直接保存回字节,一旦您退出WordprocessingDocument.Open()
块,但仍在using (MemoryStream mem = new MemoryStream() { ... }
语句内:
// Convert
byteArray = mem.ToArray()
这将会返回你的Word文档byte[]
。