protected PackagePart clonePackagePart(PackagePart pp) { PackagePart new_pp = package.CreatePart(pp.Uri, pp.ContentType, CompressionOption.Normal); using (Stream s_read = pp.GetStream()) { using (Stream s_write = new PackagePartStream(new_pp.GetStream(FileMode.Create))) { byte[] buffer = new byte[32768]; int read; while ((read = s_read.Read(buffer, 0, buffer.Length)) > 0) { s_write.Write(buffer, 0, read); } } } return new_pp; }
private void merge_images(PackagePart remote_pp, DocX remote_document, XDocument remote_mainDoc, String contentType) { // Before doing any other work, check to see if this image is actually referenced in the document. // In my testing I have found cases of Images inside documents that are not referenced var remote_rel = remote_document.mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(remote_pp.Uri.OriginalString.Replace("/word/", ""))).FirstOrDefault(); if (remote_rel == null) { remote_rel = remote_document.mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(remote_pp.Uri.OriginalString)).FirstOrDefault(); if (remote_rel == null) return; } String remote_Id = remote_rel.Id; String remote_hash = ComputeMD5HashString(remote_pp.GetStream()); var image_parts = package.GetParts().Where(pp => pp.ContentType.Equals(contentType)); bool found = false; foreach (var part in image_parts) { String local_hash = ComputeMD5HashString(part.GetStream()); if (local_hash.Equals(remote_hash)) { // This image already exists in this document. found = true; var local_rel = mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(part.Uri.OriginalString.Replace("/word/", ""))).FirstOrDefault(); if (local_rel == null) { local_rel = mainPart.GetRelationships().Where(r => r.TargetUri.OriginalString.Equals(part.Uri.OriginalString)).FirstOrDefault(); } if (local_rel != null) { String new_Id = local_rel.Id; // Replace all instances of remote_Id in the local document with local_Id var elems = remote_mainDoc.Descendants(XName.Get("blip", a.NamespaceName)); foreach (var elem in elems) { XAttribute embed = elem.Attribute(XName.Get("embed", r.NamespaceName)); if (embed != null && embed.Value == remote_Id) { embed.SetValue(new_Id); } } // Replace all instances of remote_Id in the local document with local_Id (for shapes as well) var v_elems = remote_mainDoc.Descendants(XName.Get("imagedata", v.NamespaceName)); foreach (var elem in v_elems) { XAttribute id = elem.Attribute(XName.Get("id", r.NamespaceName)); if (id != null && id.Value == remote_Id) { id.SetValue(new_Id); } } } break; } } // This image does not exist in this document. if (!found) { String new_uri = remote_pp.Uri.OriginalString; new_uri = new_uri.Remove(new_uri.LastIndexOf("/")); //new_uri = new_uri.Replace("word/", ""); new_uri += "/" + Guid.NewGuid() + contentType.Replace("image/", "."); if (!new_uri.StartsWith("/")) new_uri = "/" + new_uri; PackagePart new_pp = package.CreatePart(new Uri(new_uri, UriKind.Relative), remote_pp.ContentType, CompressionOption.Normal); using (Stream s_read = remote_pp.GetStream()) { using (Stream s_write = new PackagePartStream(new_pp.GetStream(FileMode.Create))) { byte[] buffer = new byte[32768]; int read; while ((read = s_read.Read(buffer, 0, buffer.Length)) > 0) { s_write.Write(buffer, 0, read); } } } PackageRelationship pr = mainPart.CreateRelationship(new Uri(new_uri, UriKind.Relative), TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); String new_Id = pr.Id; //Check if the remote relationship id is a default rId from Word Match defRelId = Regex.Match(remote_Id, @"rId\d+", RegexOptions.IgnoreCase); // Replace all instances of remote_Id in the local document with local_Id var elems = remote_mainDoc.Descendants(XName.Get("blip", a.NamespaceName)); foreach (var elem in elems) { XAttribute embed = elem.Attribute(XName.Get("embed", r.NamespaceName)); if (embed != null && embed.Value == remote_Id) { embed.SetValue(new_Id); } } if (!defRelId.Success) { // Replace all instances of remote_Id in the local document with local_Id var elems_local = mainDoc.Descendants(XName.Get("blip", a.NamespaceName)); foreach (var elem in elems_local) { XAttribute embed = elem.Attribute(XName.Get("embed", r.NamespaceName)); if (embed != null && embed.Value == remote_Id) { embed.SetValue(new_Id); } } // Replace all instances of remote_Id in the local document with local_Id var v_elems_local = mainDoc.Descendants(XName.Get("imagedata", v.NamespaceName)); foreach (var elem in v_elems_local) { XAttribute id = elem.Attribute(XName.Get("id", r.NamespaceName)); if (id != null && id.Value == remote_Id) { id.SetValue(new_Id); } } } // Replace all instances of remote_Id in the local document with local_Id (for shapes as well) var v_elems = remote_mainDoc.Descendants(XName.Get("imagedata", v.NamespaceName)); foreach (var elem in v_elems) { XAttribute id = elem.Attribute(XName.Get("id", r.NamespaceName)); if (id != null && id.Value == remote_Id) { id.SetValue(new_Id); } } } }
internal Image AddImage(object o, string contentType = "image/jpeg") { // Open a Stream to the new image being added. Stream newImageStream; if (o is string) newImageStream = new FileStream(o as string, FileMode.Open, FileAccess.Read); else newImageStream = o as Stream; // Get all image parts in word\document.xml PackageRelationshipCollection relationshipsByImages = mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); List<PackagePart> imageParts = relationshipsByImages.Select(ir => package.GetParts().FirstOrDefault(p => p.Uri.ToString().EndsWith(ir.TargetUri.ToString()))).Where(e => e != null).ToList(); foreach (PackagePart relsPart in package.GetParts().Where(part => part.Uri.ToString().Contains("/word/")).Where(part => part.ContentType.Equals("application/vnd.openxmlformats-package.relationships+xml"))) { XDocument relsPartContent; using (TextReader tr = new StreamReader(relsPart.GetStream(FileMode.Open, FileAccess.Read))) relsPartContent = XDocument.Load(tr); IEnumerable<XElement> imageRelationships = relsPartContent.Root.Elements().Where ( imageRel => imageRel.Attribute(XName.Get("Type")).Value.Equals("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") ); foreach (XElement imageRelationship in imageRelationships) { if (imageRelationship.Attribute(XName.Get("Target")) != null) { string targetMode = string.Empty; XAttribute targetModeAttibute = imageRelationship.Attribute(XName.Get("TargetMode")); if (targetModeAttibute != null) { targetMode = targetModeAttibute.Value; } if (!targetMode.Equals("External")) { string imagePartUri = Path.Combine(Path.GetDirectoryName(relsPart.Uri.ToString()), imageRelationship.Attribute(XName.Get("Target")).Value); imagePartUri = Path.GetFullPath(imagePartUri.Replace("\\_rels", string.Empty)); imagePartUri = imagePartUri.Replace(Path.GetFullPath("\\"), string.Empty).Replace("\\", "/"); if (!imagePartUri.StartsWith("/")) imagePartUri = "/" + imagePartUri; PackagePart imagePart = package.GetPart(new Uri(imagePartUri, UriKind.Relative)); imageParts.Add(imagePart); } } } } // Loop through each image part in this document. foreach (PackagePart pp in imageParts) { // Open a tempory Stream to this image part. using (Stream tempStream = pp.GetStream(FileMode.Open, FileAccess.Read)) { // Compare this image to the new image being added. if (HelperFunctions.IsSameFile(tempStream, newImageStream)) { // Get the image object for this image part string id = mainPart.GetRelationshipsByType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/image") .Where(r => r.TargetUri == pp.Uri) .Select(r => r.Id).First(); // Return the Image object return Images.Where(i => i.Id == id).First(); } } } string imgPartUriPath = string.Empty; string extension = contentType.Substring(contentType.LastIndexOf("/") + 1); do { // Create a new image part. imgPartUriPath = string.Format ( "/word/media/{0}.{1}", Guid.NewGuid(), // The unique part. extension ); } while (package.PartExists(new Uri(imgPartUriPath, UriKind.Relative))); // We are now guareenteed that imgPartUriPath is unique. PackagePart img = package.CreatePart(new Uri(imgPartUriPath, UriKind.Relative), contentType, CompressionOption.Normal); // Create a new image relationship PackageRelationship rel = mainPart.CreateRelationship(img.Uri, TargetMode.Internal, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image"); // Open a Stream to the newly created Image part. using (Stream stream = new PackagePartStream(img.GetStream(FileMode.Create, FileAccess.Write))) { // Using the Stream to the real image, copy this streams data into the newly create Image part. using (newImageStream) { byte[] bytes = new byte[newImageStream.Length]; newImageStream.Read(bytes, 0, (int)newImageStream.Length); stream.Write(bytes, 0, (int)newImageStream.Length); }// Close the Stream to the new image. }// Close the Stream to the new image part. return new Image(this, rel); }