Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Packaging/ZipPackage.cs @ 12803

Last change on this file since 12803 was 12074, checked in by sraggl, 10 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 13.4 KB
Line 
1/*******************************************************************************
2 * You may amend and distribute as you like, but don't remove this header!
3 *
4 * EPPlus provides server-side generation of Excel 2007/2010 spreadsheets.
5 * See http://www.codeplex.com/EPPlus for details.
6 *
7 * Copyright (C) 2011  Jan Källman
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
17 * See the GNU Lesser General Public License for more details.
18 *
19 * The GNU Lesser General Public License can be viewed at http://www.opensource.org/licenses/lgpl-license.php
20 * If you unfamiliar with this license or have questions about it, here is an http://www.gnu.org/licenses/gpl-faq.html
21 *
22 * All code and executables are provided "as is" with no warranty either express or implied.
23 * The author accepts no liability for any damage or loss of business that this product may cause.
24 *
25 * Code change notes:
26 *
27 * Author             Change            Date
28 *******************************************************************************
29 * Jan Källman    Added   25-Oct-2012
30 *******************************************************************************/
31using System;
32using System.Collections.Generic;
33using System.Globalization;
34using System.Linq;
35using System.Text;
36using System.IO;
37using System.Xml;
38using OfficeOpenXml.Utils;
39using OfficeOpenXml.Packaging.Ionic.Zip;
40using Ionic.Zip;
41namespace OfficeOpenXml.Packaging
42{
43    /// <summary>
44    /// Specifies whether the target is inside or outside the System.IO.Packaging.Package.
45    /// </summary>
46    public enum TargetMode
47    {
48        /// <summary>
49        /// The relationship references a part that is inside the package.
50        /// </summary>
51        Internal = 0,
52        /// <summary>
53        /// The relationship references a resource that is external to the package.
54        /// </summary>
55        External = 1,
56    }
57    /// <summary>
58    /// Represent an OOXML Zip package.
59    /// </summary>
60    public class ZipPackage : ZipPackageRelationshipBase
61    {
62        internal class ContentType
63        {
64            internal string Name;
65            internal bool IsExtension;
66            internal string Match;
67            public ContentType(string name, bool isExtension, string match)
68            {
69                Name = name;
70                IsExtension = isExtension;
71                Match = match;
72            }
73        }
74        Dictionary<string, ZipPackagePart> Parts = new Dictionary<string, ZipPackagePart>(StringComparer.InvariantCultureIgnoreCase);
75        internal Dictionary<string, ContentType> _contentTypes = new Dictionary<string, ContentType>(StringComparer.InvariantCultureIgnoreCase);
76        internal ZipPackage()
77        {
78            AddNew();
79        }
80
81        private void AddNew()
82        {
83            _contentTypes.Add("xml", new ContentType(ExcelPackage.schemaXmlExtension, true, "xml"));
84            _contentTypes.Add("rels", new ContentType(ExcelPackage.schemaRelsExtension, true, "rels"));
85        }
86
87        internal ZipPackage(Stream stream)
88        {
89            bool hasContentTypeXml = false;
90            if (stream == null || stream.Length == 0)
91            {
92                AddNew();
93            }
94            else
95            {
96                var rels = new Dictionary<string, string>();
97                stream.Seek(0, SeekOrigin.Begin);               
98                using (ZipInputStream zip = new ZipInputStream(stream))
99                {
100                    var e = zip.GetNextEntry();
101                    while (e != null)
102                    {
103                        if (e.UncompressedSize > 0)
104                        {
105                            var b = new byte[e.UncompressedSize];
106                            var size = zip.Read(b, 0, (int)e.UncompressedSize);
107                            if (e.FileName.Equals("[content_types].xml", StringComparison.InvariantCultureIgnoreCase))
108                            {
109                                AddContentTypes(Encoding.UTF8.GetString(b));
110                                hasContentTypeXml = true;
111                            }
112                            else if (e.FileName.Equals("_rels/.rels", StringComparison.InvariantCultureIgnoreCase))
113                            {
114                                ReadRelation(Encoding.UTF8.GetString(b), "");
115                            }
116                            else
117                            {
118                                if (e.FileName.EndsWith(".rels", StringComparison.InvariantCultureIgnoreCase))
119                                {
120                                    rels.Add(GetUriKey(e.FileName), Encoding.UTF8.GetString(b));
121                                }
122                                else
123                                {
124                                    var part = new ZipPackagePart(this, e);
125                                    part.Stream = new MemoryStream();
126                                    part.Stream.Write(b, 0, b.Length);
127                                    Parts.Add(GetUriKey(e.FileName), part);
128                                }
129                            }
130                        }
131                        else
132                        {
133                        }
134                        e = zip.GetNextEntry();
135                    }
136
137                    foreach (var p in Parts)
138                    {
139                        FileInfo fi = new FileInfo(p.Key);
140                        string relFile = string.Format("{0}_rels/{1}.rels", p.Key.Substring(0, p.Key.Length - fi.Name.Length), fi.Name);
141                        if (rels.ContainsKey(relFile))
142                        {
143                            p.Value.ReadRelation(rels[relFile], p.Value.Uri.OriginalString);
144                        }
145                        if (_contentTypes.ContainsKey(p.Key))
146                        {
147                            p.Value.ContentType = _contentTypes[p.Key].Name;
148                        }
149                        else if (fi.Extension.Length > 1 && _contentTypes.ContainsKey(fi.Extension.Substring(1)))
150                        {
151                            p.Value.ContentType = _contentTypes[fi.Extension.Substring(1)].Name;
152                        }
153                    }
154                    if (!hasContentTypeXml)
155                    {
156                        throw (new FileFormatException("The file is not an valid Package file. If the file is encrypted, please supply the password in the constructor."));
157                    }
158                    if (!hasContentTypeXml)
159                    {
160                        throw (new FileFormatException("The file is not an valid Package file. If the file is encrypted, please supply the password in the constructor."));
161                    }
162                    zip.Close();
163                }
164            }
165        }
166
167        private void AddContentTypes(string xml)
168        {
169            var doc = new XmlDocument();
170            XmlHelper.LoadXmlSafe(doc, xml, Encoding.UTF8);
171
172            foreach (XmlElement c in doc.DocumentElement.ChildNodes)
173            {
174                ContentType ct;
175                if (string.IsNullOrEmpty(c.GetAttribute("Extension")))
176                {
177                    ct = new ContentType(c.GetAttribute("ContentType"), false, c.GetAttribute("PartName"));
178                }
179                else
180                {
181                    ct = new ContentType(c.GetAttribute("ContentType"), true, c.GetAttribute("Extension"));
182                }
183                _contentTypes.Add(GetUriKey(ct.Match), ct);
184            }
185        }
186
187        #region Methods
188        internal ZipPackagePart CreatePart(Uri partUri, string contentType)
189        {
190            return CreatePart(partUri, contentType, CompressionLevel.Default);
191        }
192        internal ZipPackagePart CreatePart(Uri partUri, string contentType, CompressionLevel compressionLevel)
193        {
194            if (PartExists(partUri))
195            {
196                throw (new InvalidOperationException("Part already exist"));
197            }
198
199            var part = new ZipPackagePart(this, partUri, contentType, compressionLevel);
200            _contentTypes.Add(GetUriKey(part.Uri.OriginalString), new ContentType(contentType, false, part.Uri.OriginalString));
201            Parts.Add(GetUriKey(part.Uri.OriginalString), part);
202            return part;
203        }
204        internal ZipPackagePart GetPart(Uri partUri)
205        {
206            if (PartExists(partUri))
207            {
208                return Parts.Single(x => x.Key.Equals(GetUriKey(partUri.OriginalString),StringComparison.InvariantCultureIgnoreCase)).Value;
209            }
210            else
211            {
212                throw (new InvalidOperationException("Part does not exist."));
213            }
214        }
215
216        internal string GetUriKey(string uri)
217        {
218            string ret = uri;
219            if (ret[0] != '/')
220            {
221                ret = "/" + ret;
222            }
223            return ret;
224        }
225        internal bool PartExists(Uri partUri)
226        {
227            var uriKey = GetUriKey(partUri.OriginalString.ToLower(CultureInfo.InvariantCulture));
228            return Parts.Keys.Any(x => x.Equals(uriKey, StringComparison.InvariantCultureIgnoreCase));
229        }
230        #endregion
231
232        internal void DeletePart(Uri Uri)
233        {
234            var delList=new List<object[]>();
235            foreach (var p in Parts.Values)
236            {
237                foreach (var r in p.GetRelationships())
238                {
239                    if (UriHelper.ResolvePartUri(p.Uri, r.TargetUri).OriginalString.Equals(Uri.OriginalString, StringComparison.InvariantCultureIgnoreCase))
240                    {                       
241                        delList.Add(new object[]{r.Id, p});
242                    }
243                }
244            }
245            foreach (var o in delList)
246            {
247                ((ZipPackagePart)o[1]).DeleteRelationship(o[0].ToString());
248            }
249            var rels = GetPart(Uri).GetRelationships();
250            while (rels.Count > 0)
251            {
252                rels.Remove(rels.First().Id);
253            }
254            rels=null;
255            _contentTypes.Remove(GetUriKey(Uri.OriginalString));
256            //remove all relations
257            Parts.Remove(GetUriKey(Uri.OriginalString));
258           
259        }
260        internal void Save(Stream stream)
261        {
262            var enc = Encoding.UTF8;
263            ZipOutputStream os = new ZipOutputStream(stream, true);
264            os.CompressionLevel = (OfficeOpenXml.Packaging.Ionic.Zlib.CompressionLevel)_compression;           
265            /**** ContentType****/
266            var entry = os.PutNextEntry("[Content_Types].xml");
267            byte[] b = enc.GetBytes(GetContentTypeXml());
268            os.Write(b, 0, b.Length);
269            /**** Top Rels ****/
270            _rels.WriteZip(os, "_rels\\.rels");
271            ZipPackagePart ssPart=null;
272            foreach(var part in Parts.Values)
273            {
274                if (part.ContentType != ExcelPackage.contentTypeSharedString)
275                {
276                    part.WriteZip(os);
277                }
278                else
279                {
280                    ssPart = part;
281                }
282            }
283            //Shared strings must be saved after all worksheets. The ss dictionary is populated when that workheets are saved (to get the best performance).
284            if (ssPart != null)
285            {
286                ssPart.WriteZip(os);
287            }
288            os.Flush();
289            os.Close();
290            os.Dispose(); 
291           
292            //return ms;
293        }
294
295        private string GetContentTypeXml()
296        {
297            StringBuilder xml = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Types xmlns=\"http://schemas.openxmlformats.org/package/2006/content-types\">");
298            foreach (ContentType ct in _contentTypes.Values)
299            {
300                if (ct.IsExtension)
301                {
302                    xml.AppendFormat("<Default ContentType=\"{0}\" Extension=\"{1}\"/>", ct.Name, ct.Match);
303                }
304                else
305                {
306                    xml.AppendFormat("<Override ContentType=\"{0}\" PartName=\"{1}\" />", ct.Name, GetUriKey(ct.Match));
307                }
308            }
309            xml.Append("</Types>");
310            return xml.ToString();
311        }
312        internal void Flush()
313        {
314
315        }
316        internal void Close()
317        {
318           
319        }
320        CompressionLevel _compression = CompressionLevel.Default;
321        public CompressionLevel Compression
322        {
323            get
324            {
325                return _compression;
326            }
327            set
328            {
329                foreach (var part in Parts.Values)
330                {
331                    if (part.CompressionLevel == _compression)
332                    {
333                        part.CompressionLevel = value;
334                    }
335                }
336                _compression = value;
337            }
338        }
339    }
340}
Note: See TracBrowser for help on using the repository browser.