为了帮助其他人,我想更新这个帖子并在Adam上面的答案中添加一些内容。
实际上,我在Adam发表他的答案之前几天就成功地编写出了一些可工作的代码,但是它相当困难。文件确实很差,没有太多的信息可以查询。
我不知道Adam在他的答案中使用了Inline
和Run
元素,但技巧似乎在于获取Descendants<>
属性,然后您几乎可以像普通的XML映射一样解析任何元素。
byte[] docBytes = File.ReadAllBytes(_myFilePath);
using (MemoryStream ms = new MemoryStream())
{
ms.Write(docBytes, 0, docBytes.Length);
using (WordprocessingDocument wpdoc = WordprocessingDocument.Open(ms, true))
{
MainDocumentPart mainPart = wpdoc.MainDocumentPart;
Document doc = mainPart.Document;
}
}
一旦您掌握了这个基础,查找东西就相当容易了,尽管您必须弄清楚每个元素的名称。例如,<pic:nvPicPr>
是 Picture.NonVisualPictureProperties
等等。
正如Adam所说,你需要找到要替换图像的Blip
元素。但是,您需要找到相应于您尝试替换的图像的正确blip。
Adam展示了一种使用Inline
元素的方法。我直接深入查找了所有图片元素。我不确定哪种方法更好或更健壮(我不知道xml结构在文档之间是否一致,是否会导致代码出错)。
Blip GetBlipForPicture(string picName, Document document)
{
return document.Descendants<Picture>()
.Where(p => picName == p.NonVisualPictureProperties.NonVisualDrawingProperties.Name)
.Select(p => p.BlipFill.Blip)
.Single(); // return First or ToList or whatever here, there can be more than one
}
可以查看Adam的XML示例,以理解这里的不同元素,并了解我正在搜索的内容。
在Embed
属性中,该"blip"具有一个ID,例如:<a:blip r:embed="rId4" cstate="print" />
,它的作用是将"Blip"映射到Media文件夹中的图像(如果你将.docx重命名为.zip并解压缩,就可以看到所有这些文件和文件夹)。你可以在_rels\document.xml.rels
中找到此映射:
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/image1.png" />
因此,您需要添加一个新的图像,然后将此"blip"指向您新创建的图像的ID。
ImagePart newImg = mainPart.AddImagePart(ImagePartType.Png);
newImg .FeedData(File.Open(_myImgPath, FileMode.Open, FileAccess.Read));
Blip blip = GetBlipForPicture("MyPlaceholder.png", doc);
blip.Embed = mainPart.GetIdOfPart(newImg);
我猜这只是将旧图像留在媒体文件夹中,这并不理想,尽管它可能足够聪明地进行垃圾收集。也许有更好的方法,但我找不到。
无论如何,这就是你想要的。这个帖子现在是如何在网络上的任何地方交换图像的最完整文档(我知道这一点,我花了几个小时搜索)。因此,希望一些人会发现它有用.