1 | // ZipFile.AddUpdate.cs
|
---|
2 | // ------------------------------------------------------------------
|
---|
3 | //
|
---|
4 | // Copyright (c) 2009-2011 Dino Chiesa.
|
---|
5 | // All rights reserved.
|
---|
6 | //
|
---|
7 | // This code module is part of DotNetZip, a zipfile class library.
|
---|
8 | //
|
---|
9 | // ------------------------------------------------------------------
|
---|
10 | //
|
---|
11 | // This code is licensed under the Microsoft Public License.
|
---|
12 | // See the file License.txt for the license details.
|
---|
13 | // More info on: http://dotnetzip.codeplex.com
|
---|
14 | //
|
---|
15 | // ------------------------------------------------------------------
|
---|
16 | //
|
---|
17 | // last saved (in emacs):
|
---|
18 | // Time-stamp: <2011-November-01 13:56:58>
|
---|
19 | //
|
---|
20 | // ------------------------------------------------------------------
|
---|
21 | //
|
---|
22 | // This module defines the methods for Adding and Updating entries in
|
---|
23 | // the ZipFile.
|
---|
24 | //
|
---|
25 | // ------------------------------------------------------------------
|
---|
26 | //
|
---|
27 |
|
---|
28 |
|
---|
29 | using System;
|
---|
30 | using System.IO;
|
---|
31 | using System.Collections.Generic;
|
---|
32 |
|
---|
33 | namespace OfficeOpenXml.Packaging.Ionic.Zip
|
---|
34 | {
|
---|
35 | internal partial class ZipFile
|
---|
36 | {
|
---|
37 | /// <summary>
|
---|
38 | /// Adds an item, either a file or a directory, to a zip file archive.
|
---|
39 | /// </summary>
|
---|
40 | ///
|
---|
41 | /// <remarks>
|
---|
42 | /// <para>
|
---|
43 | /// This method is handy if you are adding things to zip archive and don't
|
---|
44 | /// want to bother distinguishing between directories or files. Any files are
|
---|
45 | /// added as single entries. A directory added through this method is added
|
---|
46 | /// recursively: all files and subdirectories contained within the directory
|
---|
47 | /// are added to the <c>ZipFile</c>.
|
---|
48 | /// </para>
|
---|
49 | ///
|
---|
50 | /// <para>
|
---|
51 | /// The name of the item may be a relative path or a fully-qualified
|
---|
52 | /// path. Remember, the items contained in <c>ZipFile</c> instance get written
|
---|
53 | /// to the disk only when you call <see cref="ZipFile.Save()"/> or a similar
|
---|
54 | /// save method.
|
---|
55 | /// </para>
|
---|
56 | ///
|
---|
57 | /// <para>
|
---|
58 | /// The directory name used for the file within the archive is the same
|
---|
59 | /// as the directory name (potentially a relative path) specified in the
|
---|
60 | /// <paramref name="fileOrDirectoryName"/>.
|
---|
61 | /// </para>
|
---|
62 | ///
|
---|
63 | /// <para>
|
---|
64 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
65 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
66 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
67 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
68 | /// respective values at the time of this call will be applied to the
|
---|
69 | /// <c>ZipEntry</c> added.
|
---|
70 | /// </para>
|
---|
71 | ///
|
---|
72 | /// </remarks>
|
---|
73 | ///
|
---|
74 | /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/>
|
---|
75 | /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/>
|
---|
76 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/>
|
---|
77 | ///
|
---|
78 | /// <overloads>This method has two overloads.</overloads>
|
---|
79 | /// <param name="fileOrDirectoryName">
|
---|
80 | /// the name of the file or directory to add.</param>
|
---|
81 | ///
|
---|
82 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
83 | public ZipEntry AddItem(string fileOrDirectoryName)
|
---|
84 | {
|
---|
85 | return AddItem(fileOrDirectoryName, null);
|
---|
86 | }
|
---|
87 |
|
---|
88 |
|
---|
89 | /// <summary>
|
---|
90 | /// Adds an item, either a file or a directory, to a zip file archive,
|
---|
91 | /// explicitly specifying the directory path to be used in the archive.
|
---|
92 | /// </summary>
|
---|
93 | ///
|
---|
94 | /// <remarks>
|
---|
95 | /// <para>
|
---|
96 | /// If adding a directory, the add is recursive on all files and
|
---|
97 | /// subdirectories contained within it.
|
---|
98 | /// </para>
|
---|
99 | /// <para>
|
---|
100 | /// The name of the item may be a relative path or a fully-qualified path.
|
---|
101 | /// The item added by this call to the <c>ZipFile</c> is not read from the
|
---|
102 | /// disk nor written to the zip file archive until the application calls
|
---|
103 | /// Save() on the <c>ZipFile</c>.
|
---|
104 | /// </para>
|
---|
105 | ///
|
---|
106 | /// <para>
|
---|
107 | /// This version of the method allows the caller to explicitly specify the
|
---|
108 | /// directory path to be used in the archive, which would override the
|
---|
109 | /// "natural" path of the filesystem file.
|
---|
110 | /// </para>
|
---|
111 | ///
|
---|
112 | /// <para>
|
---|
113 | /// Encryption will be used on the file data if the <c>Password</c> has
|
---|
114 | /// been set on the <c>ZipFile</c> object, prior to calling this method.
|
---|
115 | /// </para>
|
---|
116 | ///
|
---|
117 | /// <para>
|
---|
118 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
119 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
120 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
121 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
122 | /// respective values at the time of this call will be applied to the
|
---|
123 | /// <c>ZipEntry</c> added.
|
---|
124 | /// </para>
|
---|
125 | ///
|
---|
126 | /// </remarks>
|
---|
127 | ///
|
---|
128 | /// <exception cref="System.IO.FileNotFoundException">
|
---|
129 | /// Thrown if the file or directory passed in does not exist.
|
---|
130 | /// </exception>
|
---|
131 | ///
|
---|
132 | /// <param name="fileOrDirectoryName">the name of the file or directory to add.
|
---|
133 | /// </param>
|
---|
134 | ///
|
---|
135 | /// <param name="directoryPathInArchive">
|
---|
136 | /// The name of the directory path to use within the zip archive. This path
|
---|
137 | /// need not refer to an extant directory in the current filesystem. If the
|
---|
138 | /// files within the zip are later extracted, this is the path used for the
|
---|
139 | /// extracted file. Passing <c>null</c> (<c>Nothing</c> in VB) will use the
|
---|
140 | /// path on the fileOrDirectoryName. Passing the empty string ("") will
|
---|
141 | /// insert the item at the root path within the archive.
|
---|
142 | /// </param>
|
---|
143 | ///
|
---|
144 | /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string, string)"/>
|
---|
145 | /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/>
|
---|
146 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string, string)"/>
|
---|
147 | ///
|
---|
148 | /// <example>
|
---|
149 | /// This example shows how to zip up a set of files into a flat hierarchy,
|
---|
150 | /// regardless of where in the filesystem the files originated. The resulting
|
---|
151 | /// zip archive will contain a toplevel directory named "flat", which itself
|
---|
152 | /// will contain files Readme.txt, MyProposal.docx, and Image1.jpg. A
|
---|
153 | /// subdirectory under "flat" called SupportFiles will contain all the files
|
---|
154 | /// in the "c:\SupportFiles" directory on disk.
|
---|
155 | ///
|
---|
156 | /// <code>
|
---|
157 | /// String[] itemnames= {
|
---|
158 | /// "c:\\fixedContent\\Readme.txt",
|
---|
159 | /// "MyProposal.docx",
|
---|
160 | /// "c:\\SupportFiles", // a directory
|
---|
161 | /// "images\\Image1.jpg"
|
---|
162 | /// };
|
---|
163 | ///
|
---|
164 | /// try
|
---|
165 | /// {
|
---|
166 | /// using (ZipFile zip = new ZipFile())
|
---|
167 | /// {
|
---|
168 | /// for (int i = 1; i < itemnames.Length; i++)
|
---|
169 | /// {
|
---|
170 | /// // will add Files or Dirs, recurses and flattens subdirectories
|
---|
171 | /// zip.AddItem(itemnames[i],"flat");
|
---|
172 | /// }
|
---|
173 | /// zip.Save(ZipToCreate);
|
---|
174 | /// }
|
---|
175 | /// }
|
---|
176 | /// catch (System.Exception ex1)
|
---|
177 | /// {
|
---|
178 | /// System.Console.Error.WriteLine("exception: {0}", ex1);
|
---|
179 | /// }
|
---|
180 | /// </code>
|
---|
181 | ///
|
---|
182 | /// <code lang="VB">
|
---|
183 | /// Dim itemnames As String() = _
|
---|
184 | /// New String() { "c:\fixedContent\Readme.txt", _
|
---|
185 | /// "MyProposal.docx", _
|
---|
186 | /// "SupportFiles", _
|
---|
187 | /// "images\Image1.jpg" }
|
---|
188 | /// Try
|
---|
189 | /// Using zip As New ZipFile
|
---|
190 | /// Dim i As Integer
|
---|
191 | /// For i = 1 To itemnames.Length - 1
|
---|
192 | /// ' will add Files or Dirs, recursing and flattening subdirectories.
|
---|
193 | /// zip.AddItem(itemnames(i), "flat")
|
---|
194 | /// Next i
|
---|
195 | /// zip.Save(ZipToCreate)
|
---|
196 | /// End Using
|
---|
197 | /// Catch ex1 As Exception
|
---|
198 | /// Console.Error.WriteLine("exception: {0}", ex1.ToString())
|
---|
199 | /// End Try
|
---|
200 | /// </code>
|
---|
201 | /// </example>
|
---|
202 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
203 | public ZipEntry AddItem(String fileOrDirectoryName, String directoryPathInArchive)
|
---|
204 | {
|
---|
205 | if (File.Exists(fileOrDirectoryName))
|
---|
206 | return AddFile(fileOrDirectoryName, directoryPathInArchive);
|
---|
207 |
|
---|
208 | if (Directory.Exists(fileOrDirectoryName))
|
---|
209 | return AddDirectory(fileOrDirectoryName, directoryPathInArchive);
|
---|
210 |
|
---|
211 | throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!",
|
---|
212 | fileOrDirectoryName));
|
---|
213 | }
|
---|
214 |
|
---|
215 | /// <summary>
|
---|
216 | /// Adds a File to a Zip file archive.
|
---|
217 | /// </summary>
|
---|
218 | /// <remarks>
|
---|
219 | ///
|
---|
220 | /// <para>
|
---|
221 | /// This call collects metadata for the named file in the filesystem,
|
---|
222 | /// including the file attributes and the timestamp, and inserts that metadata
|
---|
223 | /// into the resulting ZipEntry. Only when the application calls Save() on
|
---|
224 | /// the <c>ZipFile</c>, does DotNetZip read the file from the filesystem and
|
---|
225 | /// then write the content to the zip file archive.
|
---|
226 | /// </para>
|
---|
227 | ///
|
---|
228 | /// <para>
|
---|
229 | /// This method will throw an exception if an entry with the same name already
|
---|
230 | /// exists in the <c>ZipFile</c>.
|
---|
231 | /// </para>
|
---|
232 | ///
|
---|
233 | /// <para>
|
---|
234 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
235 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
236 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
237 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
238 | /// respective values at the time of this call will be applied to the
|
---|
239 | /// <c>ZipEntry</c> added.
|
---|
240 | /// </para>
|
---|
241 | ///
|
---|
242 | /// </remarks>
|
---|
243 | ///
|
---|
244 | /// <example>
|
---|
245 | /// <para>
|
---|
246 | /// In this example, three files are added to a Zip archive. The ReadMe.txt
|
---|
247 | /// file will be placed in the root of the archive. The .png file will be
|
---|
248 | /// placed in a folder within the zip called photos\personal. The pdf file
|
---|
249 | /// will be included into a folder within the zip called Desktop.
|
---|
250 | /// </para>
|
---|
251 | /// <code>
|
---|
252 | /// try
|
---|
253 | /// {
|
---|
254 | /// using (ZipFile zip = new ZipFile())
|
---|
255 | /// {
|
---|
256 | /// zip.AddFile("c:\\photos\\personal\\7440-N49th.png");
|
---|
257 | /// zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf");
|
---|
258 | /// zip.AddFile("ReadMe.txt");
|
---|
259 | ///
|
---|
260 | /// zip.Save("Package.zip");
|
---|
261 | /// }
|
---|
262 | /// }
|
---|
263 | /// catch (System.Exception ex1)
|
---|
264 | /// {
|
---|
265 | /// System.Console.Error.WriteLine("exception: " + ex1);
|
---|
266 | /// }
|
---|
267 | /// </code>
|
---|
268 | ///
|
---|
269 | /// <code lang="VB">
|
---|
270 | /// Try
|
---|
271 | /// Using zip As ZipFile = New ZipFile
|
---|
272 | /// zip.AddFile("c:\photos\personal\7440-N49th.png")
|
---|
273 | /// zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf")
|
---|
274 | /// zip.AddFile("ReadMe.txt")
|
---|
275 | /// zip.Save("Package.zip")
|
---|
276 | /// End Using
|
---|
277 | /// Catch ex1 As Exception
|
---|
278 | /// Console.Error.WriteLine("exception: {0}", ex1.ToString)
|
---|
279 | /// End Try
|
---|
280 | /// </code>
|
---|
281 | /// </example>
|
---|
282 | ///
|
---|
283 | /// <overloads>This method has two overloads.</overloads>
|
---|
284 | ///
|
---|
285 | /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/>
|
---|
286 | /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/>
|
---|
287 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/>
|
---|
288 | ///
|
---|
289 | /// <param name="fileName">
|
---|
290 | /// The name of the file to add. It should refer to a file in the filesystem.
|
---|
291 | /// The name of the file may be a relative path or a fully-qualified path.
|
---|
292 | /// </param>
|
---|
293 | /// <returns>The <c>ZipEntry</c> corresponding to the File added.</returns>
|
---|
294 | public ZipEntry AddFile(string fileName)
|
---|
295 | {
|
---|
296 | return AddFile(fileName, null);
|
---|
297 | }
|
---|
298 |
|
---|
299 |
|
---|
300 |
|
---|
301 |
|
---|
302 |
|
---|
303 | /// <summary>
|
---|
304 | /// Adds a File to a Zip file archive, potentially overriding the path to be
|
---|
305 | /// used within the zip archive.
|
---|
306 | /// </summary>
|
---|
307 | ///
|
---|
308 | /// <remarks>
|
---|
309 | /// <para>
|
---|
310 | /// The file added by this call to the <c>ZipFile</c> is not written to the
|
---|
311 | /// zip file archive until the application calls Save() on the <c>ZipFile</c>.
|
---|
312 | /// </para>
|
---|
313 | ///
|
---|
314 | /// <para>
|
---|
315 | /// This method will throw an exception if an entry with the same name already
|
---|
316 | /// exists in the <c>ZipFile</c>.
|
---|
317 | /// </para>
|
---|
318 | ///
|
---|
319 | /// <para>
|
---|
320 | /// This version of the method allows the caller to explicitly specify the
|
---|
321 | /// directory path to be used in the archive.
|
---|
322 | /// </para>
|
---|
323 | ///
|
---|
324 | /// <para>
|
---|
325 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
326 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
327 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
328 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
329 | /// respective values at the time of this call will be applied to the
|
---|
330 | /// <c>ZipEntry</c> added.
|
---|
331 | /// </para>
|
---|
332 | ///
|
---|
333 | /// </remarks>
|
---|
334 | ///
|
---|
335 | /// <example>
|
---|
336 | /// <para>
|
---|
337 | /// In this example, three files are added to a Zip archive. The ReadMe.txt
|
---|
338 | /// file will be placed in the root of the archive. The .png file will be
|
---|
339 | /// placed in a folder within the zip called images. The pdf file will be
|
---|
340 | /// included into a folder within the zip called files\docs, and will be
|
---|
341 | /// encrypted with the given password.
|
---|
342 | /// </para>
|
---|
343 | /// <code>
|
---|
344 | /// try
|
---|
345 | /// {
|
---|
346 | /// using (ZipFile zip = new ZipFile())
|
---|
347 | /// {
|
---|
348 | /// // the following entry will be inserted at the root in the archive.
|
---|
349 | /// zip.AddFile("c:\\datafiles\\ReadMe.txt", "");
|
---|
350 | /// // this image file will be inserted into the "images" directory in the archive.
|
---|
351 | /// zip.AddFile("c:\\photos\\personal\\7440-N49th.png", "images");
|
---|
352 | /// // the following will result in a password-protected file called
|
---|
353 | /// // files\\docs\\2008-Regional-Sales-Report.pdf in the archive.
|
---|
354 | /// zip.Password = "EncryptMe!";
|
---|
355 | /// zip.AddFile("c:\\Desktop\\2008-Regional-Sales-Report.pdf", "files\\docs");
|
---|
356 | /// zip.Save("Archive.zip");
|
---|
357 | /// }
|
---|
358 | /// }
|
---|
359 | /// catch (System.Exception ex1)
|
---|
360 | /// {
|
---|
361 | /// System.Console.Error.WriteLine("exception: {0}", ex1);
|
---|
362 | /// }
|
---|
363 | /// </code>
|
---|
364 | ///
|
---|
365 | /// <code lang="VB">
|
---|
366 | /// Try
|
---|
367 | /// Using zip As ZipFile = New ZipFile
|
---|
368 | /// ' the following entry will be inserted at the root in the archive.
|
---|
369 | /// zip.AddFile("c:\datafiles\ReadMe.txt", "")
|
---|
370 | /// ' this image file will be inserted into the "images" directory in the archive.
|
---|
371 | /// zip.AddFile("c:\photos\personal\7440-N49th.png", "images")
|
---|
372 | /// ' the following will result in a password-protected file called
|
---|
373 | /// ' files\\docs\\2008-Regional-Sales-Report.pdf in the archive.
|
---|
374 | /// zip.Password = "EncryptMe!"
|
---|
375 | /// zip.AddFile("c:\Desktop\2008-Regional-Sales-Report.pdf", "files\documents")
|
---|
376 | /// zip.Save("Archive.zip")
|
---|
377 | /// End Using
|
---|
378 | /// Catch ex1 As Exception
|
---|
379 | /// Console.Error.WriteLine("exception: {0}", ex1)
|
---|
380 | /// End Try
|
---|
381 | /// </code>
|
---|
382 | /// </example>
|
---|
383 | ///
|
---|
384 | /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string,string)"/>
|
---|
385 | /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/>
|
---|
386 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string,string)"/>
|
---|
387 | ///
|
---|
388 | /// <param name="fileName">
|
---|
389 | /// The name of the file to add. The name of the file may be a relative path
|
---|
390 | /// or a fully-qualified path.
|
---|
391 | /// </param>
|
---|
392 | ///
|
---|
393 | /// <param name="directoryPathInArchive">
|
---|
394 | /// Specifies a directory path to use to override any path in the fileName.
|
---|
395 | /// This path may, or may not, correspond to a real directory in the current
|
---|
396 | /// filesystem. If the files within the zip are later extracted, this is the
|
---|
397 | /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
|
---|
398 | /// VB) will use the path on the fileName, if any. Passing the empty string
|
---|
399 | /// ("") will insert the item at the root path within the archive.
|
---|
400 | /// </param>
|
---|
401 | ///
|
---|
402 | /// <returns>The <c>ZipEntry</c> corresponding to the file added.</returns>
|
---|
403 | public ZipEntry AddFile(string fileName, String directoryPathInArchive)
|
---|
404 | {
|
---|
405 | string nameInArchive = ZipEntry.NameInArchive(fileName, directoryPathInArchive);
|
---|
406 | ZipEntry ze = ZipEntry.CreateFromFile(fileName, nameInArchive);
|
---|
407 | if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", fileName);
|
---|
408 | return _InternalAddEntry(ze);
|
---|
409 | }
|
---|
410 |
|
---|
411 |
|
---|
412 | /// <summary>
|
---|
413 | /// This method removes a collection of entries from the <c>ZipFile</c>.
|
---|
414 | /// </summary>
|
---|
415 | ///
|
---|
416 | /// <param name="entriesToRemove">
|
---|
417 | /// A collection of ZipEntry instances from this zip file to be removed. For
|
---|
418 | /// example, you can pass in an array of ZipEntry instances; or you can call
|
---|
419 | /// SelectEntries(), and then add or remove entries from that
|
---|
420 | /// ICollection<ZipEntry> (ICollection(Of ZipEntry) in VB), and pass
|
---|
421 | /// that ICollection to this method.
|
---|
422 | /// </param>
|
---|
423 | ///
|
---|
424 | /// <seealso cref="Ionic.Zip.ZipFile.SelectEntries(String)" />
|
---|
425 | /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(String)" />
|
---|
426 | public void RemoveEntries(System.Collections.Generic.ICollection<ZipEntry> entriesToRemove)
|
---|
427 | {
|
---|
428 | if (entriesToRemove == null)
|
---|
429 | throw new ArgumentNullException("entriesToRemove");
|
---|
430 |
|
---|
431 | foreach (ZipEntry e in entriesToRemove)
|
---|
432 | {
|
---|
433 | this.RemoveEntry(e);
|
---|
434 | }
|
---|
435 | }
|
---|
436 |
|
---|
437 |
|
---|
438 | /// <summary>
|
---|
439 | /// This method removes a collection of entries from the <c>ZipFile</c>, by name.
|
---|
440 | /// </summary>
|
---|
441 | ///
|
---|
442 | /// <param name="entriesToRemove">
|
---|
443 | /// A collection of strings that refer to names of entries to be removed
|
---|
444 | /// from the <c>ZipFile</c>. For example, you can pass in an array or a
|
---|
445 | /// List of Strings that provide the names of entries to be removed.
|
---|
446 | /// </param>
|
---|
447 | ///
|
---|
448 | /// <seealso cref="Ionic.Zip.ZipFile.SelectEntries(String)" />
|
---|
449 | /// <seealso cref="Ionic.Zip.ZipFile.RemoveSelectedEntries(String)" />
|
---|
450 | public void RemoveEntries(System.Collections.Generic.ICollection<String> entriesToRemove)
|
---|
451 | {
|
---|
452 | if (entriesToRemove == null)
|
---|
453 | throw new ArgumentNullException("entriesToRemove");
|
---|
454 |
|
---|
455 | foreach (String e in entriesToRemove)
|
---|
456 | {
|
---|
457 | this.RemoveEntry(e);
|
---|
458 | }
|
---|
459 | }
|
---|
460 |
|
---|
461 |
|
---|
462 | /// <summary>
|
---|
463 | /// This method adds a set of files to the <c>ZipFile</c>.
|
---|
464 | /// </summary>
|
---|
465 | ///
|
---|
466 | /// <remarks>
|
---|
467 | /// <para>
|
---|
468 | /// Use this method to add a set of files to the zip archive, in one call.
|
---|
469 | /// For example, a list of files received from
|
---|
470 | /// <c>System.IO.Directory.GetFiles()</c> can be added to a zip archive in one
|
---|
471 | /// call.
|
---|
472 | /// </para>
|
---|
473 | ///
|
---|
474 | /// <para>
|
---|
475 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
476 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
477 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
478 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
479 | /// respective values at the time of this call will be applied to each
|
---|
480 | /// ZipEntry added.
|
---|
481 | /// </para>
|
---|
482 | /// </remarks>
|
---|
483 | ///
|
---|
484 | /// <param name="fileNames">
|
---|
485 | /// The collection of names of the files to add. Each string should refer to a
|
---|
486 | /// file in the filesystem. The name of the file may be a relative path or a
|
---|
487 | /// fully-qualified path.
|
---|
488 | /// </param>
|
---|
489 | ///
|
---|
490 | /// <example>
|
---|
491 | /// This example shows how to create a zip file, and add a few files into it.
|
---|
492 | /// <code>
|
---|
493 | /// String ZipFileToCreate = "archive1.zip";
|
---|
494 | /// String DirectoryToZip = "c:\\reports";
|
---|
495 | /// using (ZipFile zip = new ZipFile())
|
---|
496 | /// {
|
---|
497 | /// // Store all files found in the top level directory, into the zip archive.
|
---|
498 | /// String[] filenames = System.IO.Directory.GetFiles(DirectoryToZip);
|
---|
499 | /// zip.AddFiles(filenames);
|
---|
500 | /// zip.Save(ZipFileToCreate);
|
---|
501 | /// }
|
---|
502 | /// </code>
|
---|
503 | ///
|
---|
504 | /// <code lang="VB">
|
---|
505 | /// Dim ZipFileToCreate As String = "archive1.zip"
|
---|
506 | /// Dim DirectoryToZip As String = "c:\reports"
|
---|
507 | /// Using zip As ZipFile = New ZipFile
|
---|
508 | /// ' Store all files found in the top level directory, into the zip archive.
|
---|
509 | /// Dim filenames As String() = System.IO.Directory.GetFiles(DirectoryToZip)
|
---|
510 | /// zip.AddFiles(filenames)
|
---|
511 | /// zip.Save(ZipFileToCreate)
|
---|
512 | /// End Using
|
---|
513 | /// </code>
|
---|
514 | /// </example>
|
---|
515 | ///
|
---|
516 | /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
|
---|
517 | public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames)
|
---|
518 | {
|
---|
519 | this.AddFiles(fileNames, null);
|
---|
520 | }
|
---|
521 |
|
---|
522 |
|
---|
523 | /// <summary>
|
---|
524 | /// Adds or updates a set of files in the <c>ZipFile</c>.
|
---|
525 | /// </summary>
|
---|
526 | ///
|
---|
527 | /// <remarks>
|
---|
528 | /// <para>
|
---|
529 | /// Any files that already exist in the archive are updated. Any files that
|
---|
530 | /// don't yet exist in the archive are added.
|
---|
531 | /// </para>
|
---|
532 | ///
|
---|
533 | /// <para>
|
---|
534 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
535 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
536 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
537 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
538 | /// respective values at the time of this call will be applied to each
|
---|
539 | /// ZipEntry added.
|
---|
540 | /// </para>
|
---|
541 | /// </remarks>
|
---|
542 | ///
|
---|
543 | /// <param name="fileNames">
|
---|
544 | /// The collection of names of the files to update. Each string should refer to a file in
|
---|
545 | /// the filesystem. The name of the file may be a relative path or a fully-qualified path.
|
---|
546 | /// </param>
|
---|
547 | ///
|
---|
548 | public void UpdateFiles(System.Collections.Generic.IEnumerable<String> fileNames)
|
---|
549 | {
|
---|
550 | this.UpdateFiles(fileNames, null);
|
---|
551 | }
|
---|
552 |
|
---|
553 |
|
---|
554 | /// <summary>
|
---|
555 | /// Adds a set of files to the <c>ZipFile</c>, using the
|
---|
556 | /// specified directory path in the archive.
|
---|
557 | /// </summary>
|
---|
558 | ///
|
---|
559 | /// <remarks>
|
---|
560 | /// <para>
|
---|
561 | /// Any directory structure that may be present in the
|
---|
562 | /// filenames contained in the list is "flattened" in the
|
---|
563 | /// archive. Each file in the list is added to the archive in
|
---|
564 | /// the specified top-level directory.
|
---|
565 | /// </para>
|
---|
566 | ///
|
---|
567 | /// <para>
|
---|
568 | /// For <c>ZipFile</c> properties including <see
|
---|
569 | /// cref="Encryption"/>, <see cref="Password"/>, <see
|
---|
570 | /// cref="SetCompression"/>, <see
|
---|
571 | /// cref="ProvisionalAlternateEncoding"/>, <see
|
---|
572 | /// cref="ExtractExistingFile"/>, <see
|
---|
573 | /// cref="ZipErrorAction"/>, and <see
|
---|
574 | /// cref="CompressionLevel"/>, their respective values at the
|
---|
575 | /// time of this call will be applied to each ZipEntry added.
|
---|
576 | /// </para>
|
---|
577 | /// </remarks>
|
---|
578 | ///
|
---|
579 | /// <param name="fileNames">
|
---|
580 | /// The names of the files to add. Each string should refer to
|
---|
581 | /// a file in the filesystem. The name of the file may be a
|
---|
582 | /// relative path or a fully-qualified path.
|
---|
583 | /// </param>
|
---|
584 | ///
|
---|
585 | /// <param name="directoryPathInArchive">
|
---|
586 | /// Specifies a directory path to use to override any path in the file name.
|
---|
587 | /// Th is path may, or may not, correspond to a real directory in the current
|
---|
588 | /// filesystem. If the files within the zip are later extracted, this is the
|
---|
589 | /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
|
---|
590 | /// VB) will use the path on each of the <c>fileNames</c>, if any. Passing
|
---|
591 | /// the empty string ("") will insert the item at the root path within the
|
---|
592 | /// archive.
|
---|
593 | /// </param>
|
---|
594 | ///
|
---|
595 | /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
|
---|
596 | public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames, String directoryPathInArchive)
|
---|
597 | {
|
---|
598 | AddFiles(fileNames, false, directoryPathInArchive);
|
---|
599 | }
|
---|
600 |
|
---|
601 |
|
---|
602 |
|
---|
603 | /// <summary>
|
---|
604 | /// Adds a set of files to the <c>ZipFile</c>, using the specified directory
|
---|
605 | /// path in the archive, and preserving the full directory structure in the
|
---|
606 | /// filenames.
|
---|
607 | /// </summary>
|
---|
608 | ///
|
---|
609 | /// <remarks>
|
---|
610 | ///
|
---|
611 | /// <para>
|
---|
612 | /// Think of the <paramref name="directoryPathInArchive"/> as a "root" or
|
---|
613 | /// base directory used in the archive for the files that get added. when
|
---|
614 | /// <paramref name="preserveDirHierarchy"/> is true, the hierarchy of files
|
---|
615 | /// found in the filesystem will be placed, with the hierarchy intact,
|
---|
616 | /// starting at that root in the archive. When <c>preserveDirHierarchy</c>
|
---|
617 | /// is false, the path hierarchy of files is flattned, and the flattened
|
---|
618 | /// set of files gets placed in the root within the archive as specified in
|
---|
619 | /// <c>directoryPathInArchive</c>.
|
---|
620 | /// </para>
|
---|
621 | ///
|
---|
622 | /// <para>
|
---|
623 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
624 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
625 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
626 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
627 | /// respective values at the time of this call will be applied to each
|
---|
628 | /// ZipEntry added.
|
---|
629 | /// </para>
|
---|
630 | ///
|
---|
631 | /// </remarks>
|
---|
632 | ///
|
---|
633 | /// <param name="fileNames">
|
---|
634 | /// The names of the files to add. Each string should refer to a file in the
|
---|
635 | /// filesystem. The name of the file may be a relative path or a
|
---|
636 | /// fully-qualified path.
|
---|
637 | /// </param>
|
---|
638 | ///
|
---|
639 | /// <param name="directoryPathInArchive">
|
---|
640 | /// Specifies a directory path to use as a prefix for each entry name.
|
---|
641 | /// This path may, or may not, correspond to a real directory in the current
|
---|
642 | /// filesystem. If the files within the zip are later extracted, this is the
|
---|
643 | /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
|
---|
644 | /// VB) will use the path on each of the <c>fileNames</c>, if any. Passing
|
---|
645 | /// the empty string ("") will insert the item at the root path within the
|
---|
646 | /// archive.
|
---|
647 | /// </param>
|
---|
648 | ///
|
---|
649 | /// <param name="preserveDirHierarchy">
|
---|
650 | /// whether the entries in the zip archive will reflect the directory
|
---|
651 | /// hierarchy that is present in the various filenames. For example, if
|
---|
652 | /// <paramref name="fileNames"/> includes two paths,
|
---|
653 | /// \Animalia\Chordata\Mammalia\Info.txt and
|
---|
654 | /// \Plantae\Magnoliophyta\Dicotyledon\Info.txt, then calling this method
|
---|
655 | /// with <paramref name="preserveDirHierarchy"/> = <c>false</c> will
|
---|
656 | /// result in an exception because of a duplicate entry name, while
|
---|
657 | /// calling this method with <paramref name="preserveDirHierarchy"/> =
|
---|
658 | /// <c>true</c> will result in the full direcory paths being included in
|
---|
659 | /// the entries added to the ZipFile.
|
---|
660 | /// </param>
|
---|
661 | /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
|
---|
662 | public void AddFiles(System.Collections.Generic.IEnumerable<String> fileNames,
|
---|
663 | bool preserveDirHierarchy,
|
---|
664 | String directoryPathInArchive)
|
---|
665 | {
|
---|
666 | if (fileNames == null)
|
---|
667 | throw new ArgumentNullException("fileNames");
|
---|
668 |
|
---|
669 | _addOperationCanceled = false;
|
---|
670 | OnAddStarted();
|
---|
671 | if (preserveDirHierarchy)
|
---|
672 | {
|
---|
673 | foreach (var f in fileNames)
|
---|
674 | {
|
---|
675 | if (_addOperationCanceled) break;
|
---|
676 | if (directoryPathInArchive != null)
|
---|
677 | {
|
---|
678 | //string s = SharedUtilities.NormalizePath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f)));
|
---|
679 | string s = Path.GetFullPath(Path.Combine(directoryPathInArchive, Path.GetDirectoryName(f)));
|
---|
680 | this.AddFile(f, s);
|
---|
681 | }
|
---|
682 | else
|
---|
683 | this.AddFile(f, null);
|
---|
684 | }
|
---|
685 | }
|
---|
686 | else
|
---|
687 | {
|
---|
688 | foreach (var f in fileNames)
|
---|
689 | {
|
---|
690 | if (_addOperationCanceled) break;
|
---|
691 | this.AddFile(f, directoryPathInArchive);
|
---|
692 | }
|
---|
693 | }
|
---|
694 | if (!_addOperationCanceled)
|
---|
695 | OnAddCompleted();
|
---|
696 | }
|
---|
697 |
|
---|
698 |
|
---|
699 | /// <summary>
|
---|
700 | /// Adds or updates a set of files to the <c>ZipFile</c>, using the specified
|
---|
701 | /// directory path in the archive.
|
---|
702 | /// </summary>
|
---|
703 | ///
|
---|
704 | /// <remarks>
|
---|
705 | ///
|
---|
706 | /// <para>
|
---|
707 | /// Any files that already exist in the archive are updated. Any files that
|
---|
708 | /// don't yet exist in the archive are added.
|
---|
709 | /// </para>
|
---|
710 | ///
|
---|
711 | /// <para>
|
---|
712 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
713 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
714 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
715 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
716 | /// respective values at the time of this call will be applied to each
|
---|
717 | /// ZipEntry added.
|
---|
718 | /// </para>
|
---|
719 | /// </remarks>
|
---|
720 | ///
|
---|
721 | /// <param name="fileNames">
|
---|
722 | /// The names of the files to add or update. Each string should refer to a
|
---|
723 | /// file in the filesystem. The name of the file may be a relative path or a
|
---|
724 | /// fully-qualified path.
|
---|
725 | /// </param>
|
---|
726 | ///
|
---|
727 | /// <param name="directoryPathInArchive">
|
---|
728 | /// Specifies a directory path to use to override any path in the file name.
|
---|
729 | /// This path may, or may not, correspond to a real directory in the current
|
---|
730 | /// filesystem. If the files within the zip are later extracted, this is the
|
---|
731 | /// path used for the extracted file. Passing <c>null</c> (<c>Nothing</c> in
|
---|
732 | /// VB) will use the path on each of the <c>fileNames</c>, if any. Passing
|
---|
733 | /// the empty string ("") will insert the item at the root path within the
|
---|
734 | /// archive.
|
---|
735 | /// </param>
|
---|
736 | ///
|
---|
737 | /// <seealso cref="Ionic.Zip.ZipFile.AddSelectedFiles(String, String)" />
|
---|
738 | public void UpdateFiles(System.Collections.Generic.IEnumerable<String> fileNames, String directoryPathInArchive)
|
---|
739 | {
|
---|
740 | if (fileNames == null)
|
---|
741 | throw new ArgumentNullException("fileNames");
|
---|
742 |
|
---|
743 | OnAddStarted();
|
---|
744 | foreach (var f in fileNames)
|
---|
745 | this.UpdateFile(f, directoryPathInArchive);
|
---|
746 | OnAddCompleted();
|
---|
747 | }
|
---|
748 |
|
---|
749 |
|
---|
750 |
|
---|
751 |
|
---|
752 | /// <summary>
|
---|
753 | /// Adds or Updates a File in a Zip file archive.
|
---|
754 | /// </summary>
|
---|
755 | ///
|
---|
756 | /// <remarks>
|
---|
757 | /// <para>
|
---|
758 | /// This method adds a file to a zip archive, or, if the file already exists
|
---|
759 | /// in the zip archive, this method Updates the content of that given filename
|
---|
760 | /// in the zip archive. The <c>UpdateFile</c> method might more accurately be
|
---|
761 | /// called "AddOrUpdateFile".
|
---|
762 | /// </para>
|
---|
763 | ///
|
---|
764 | /// <para>
|
---|
765 | /// Upon success, there is no way for the application to learn whether the file
|
---|
766 | /// was added versus updated.
|
---|
767 | /// </para>
|
---|
768 | ///
|
---|
769 | /// <para>
|
---|
770 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
771 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
772 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
773 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
774 | /// respective values at the time of this call will be applied to the
|
---|
775 | /// <c>ZipEntry</c> added.
|
---|
776 | /// </para>
|
---|
777 | /// </remarks>
|
---|
778 | ///
|
---|
779 | /// <example>
|
---|
780 | ///
|
---|
781 | /// This example shows how to Update an existing entry in a zipfile. The first
|
---|
782 | /// call to UpdateFile adds the file to the newly-created zip archive. The
|
---|
783 | /// second call to UpdateFile updates the content for that file in the zip
|
---|
784 | /// archive.
|
---|
785 | ///
|
---|
786 | /// <code>
|
---|
787 | /// using (ZipFile zip1 = new ZipFile())
|
---|
788 | /// {
|
---|
789 | /// // UpdateFile might more accurately be called "AddOrUpdateFile"
|
---|
790 | /// zip1.UpdateFile("MyDocuments\\Readme.txt");
|
---|
791 | /// zip1.UpdateFile("CustomerList.csv");
|
---|
792 | /// zip1.Comment = "This zip archive has been created.";
|
---|
793 | /// zip1.Save("Content.zip");
|
---|
794 | /// }
|
---|
795 | ///
|
---|
796 | /// using (ZipFile zip2 = ZipFile.Read("Content.zip"))
|
---|
797 | /// {
|
---|
798 | /// zip2.UpdateFile("Updates\\Readme.txt");
|
---|
799 | /// zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed.";
|
---|
800 | /// zip2.Save();
|
---|
801 | /// }
|
---|
802 | ///
|
---|
803 | /// </code>
|
---|
804 | /// <code lang="VB">
|
---|
805 | /// Using zip1 As New ZipFile
|
---|
806 | /// ' UpdateFile might more accurately be called "AddOrUpdateFile"
|
---|
807 | /// zip1.UpdateFile("MyDocuments\Readme.txt")
|
---|
808 | /// zip1.UpdateFile("CustomerList.csv")
|
---|
809 | /// zip1.Comment = "This zip archive has been created."
|
---|
810 | /// zip1.Save("Content.zip")
|
---|
811 | /// End Using
|
---|
812 | ///
|
---|
813 | /// Using zip2 As ZipFile = ZipFile.Read("Content.zip")
|
---|
814 | /// zip2.UpdateFile("Updates\Readme.txt")
|
---|
815 | /// zip2.Comment = "This zip archive has been updated: The Readme.txt file has been changed."
|
---|
816 | /// zip2.Save
|
---|
817 | /// End Using
|
---|
818 | /// </code>
|
---|
819 | /// </example>
|
---|
820 | ///
|
---|
821 | /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/>
|
---|
822 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/>
|
---|
823 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/>
|
---|
824 | ///
|
---|
825 | /// <param name="fileName">
|
---|
826 | /// The name of the file to add or update. It should refer to a file in the
|
---|
827 | /// filesystem. The name of the file may be a relative path or a
|
---|
828 | /// fully-qualified path.
|
---|
829 | /// </param>
|
---|
830 | ///
|
---|
831 | /// <returns>
|
---|
832 | /// The <c>ZipEntry</c> corresponding to the File that was added or updated.
|
---|
833 | /// </returns>
|
---|
834 | public ZipEntry UpdateFile(string fileName)
|
---|
835 | {
|
---|
836 | return UpdateFile(fileName, null);
|
---|
837 | }
|
---|
838 |
|
---|
839 |
|
---|
840 |
|
---|
841 | /// <summary>
|
---|
842 | /// Adds or Updates a File in a Zip file archive.
|
---|
843 | /// </summary>
|
---|
844 | ///
|
---|
845 | /// <remarks>
|
---|
846 | /// <para>
|
---|
847 | /// This method adds a file to a zip archive, or, if the file already exists
|
---|
848 | /// in the zip archive, this method Updates the content of that given filename
|
---|
849 | /// in the zip archive.
|
---|
850 | /// </para>
|
---|
851 | ///
|
---|
852 | /// <para>
|
---|
853 | /// This version of the method allows the caller to explicitly specify the
|
---|
854 | /// directory path to be used in the archive. The entry to be added or
|
---|
855 | /// updated is found by using the specified directory path, combined with the
|
---|
856 | /// basename of the specified filename.
|
---|
857 | /// </para>
|
---|
858 | ///
|
---|
859 | /// <para>
|
---|
860 | /// Upon success, there is no way for the application to learn if the file was
|
---|
861 | /// added versus updated.
|
---|
862 | /// </para>
|
---|
863 | ///
|
---|
864 | /// <para>
|
---|
865 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
866 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
867 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
868 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
869 | /// respective values at the time of this call will be applied to the
|
---|
870 | /// <c>ZipEntry</c> added.
|
---|
871 | /// </para>
|
---|
872 | /// </remarks>
|
---|
873 | ///
|
---|
874 | /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string,string)"/>
|
---|
875 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string,string)"/>
|
---|
876 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string,string)"/>
|
---|
877 | ///
|
---|
878 | /// <param name="fileName">
|
---|
879 | /// The name of the file to add or update. It should refer to a file in the
|
---|
880 | /// filesystem. The name of the file may be a relative path or a
|
---|
881 | /// fully-qualified path.
|
---|
882 | /// </param>
|
---|
883 | ///
|
---|
884 | /// <param name="directoryPathInArchive">
|
---|
885 | /// Specifies a directory path to use to override any path in the
|
---|
886 | /// <c>fileName</c>. This path may, or may not, correspond to a real
|
---|
887 | /// directory in the current filesystem. If the files within the zip are
|
---|
888 | /// later extracted, this is the path used for the extracted file. Passing
|
---|
889 | /// <c>null</c> (<c>Nothing</c> in VB) will use the path on the
|
---|
890 | /// <c>fileName</c>, if any. Passing the empty string ("") will insert the
|
---|
891 | /// item at the root path within the archive.
|
---|
892 | /// </param>
|
---|
893 | ///
|
---|
894 | /// <returns>
|
---|
895 | /// The <c>ZipEntry</c> corresponding to the File that was added or updated.
|
---|
896 | /// </returns>
|
---|
897 | public ZipEntry UpdateFile(string fileName, String directoryPathInArchive)
|
---|
898 | {
|
---|
899 | // ideally this would all be transactional!
|
---|
900 | var key = ZipEntry.NameInArchive(fileName, directoryPathInArchive);
|
---|
901 | if (this[key] != null)
|
---|
902 | this.RemoveEntry(key);
|
---|
903 | return this.AddFile(fileName, directoryPathInArchive);
|
---|
904 | }
|
---|
905 |
|
---|
906 |
|
---|
907 |
|
---|
908 |
|
---|
909 |
|
---|
910 | /// <summary>
|
---|
911 | /// Add or update a directory in a zip archive.
|
---|
912 | /// </summary>
|
---|
913 | ///
|
---|
914 | /// <remarks>
|
---|
915 | /// If the specified directory does not exist in the archive, then this method
|
---|
916 | /// is equivalent to calling <c>AddDirectory()</c>. If the specified
|
---|
917 | /// directory already exists in the archive, then this method updates any
|
---|
918 | /// existing entries, and adds any new entries. Any entries that are in the
|
---|
919 | /// zip archive but not in the specified directory, are left alone. In other
|
---|
920 | /// words, the contents of the zip file will be a union of the previous
|
---|
921 | /// contents and the new files.
|
---|
922 | /// </remarks>
|
---|
923 | ///
|
---|
924 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/>
|
---|
925 | /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string)"/>
|
---|
926 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string)"/>
|
---|
927 | ///
|
---|
928 | /// <param name="directoryName">
|
---|
929 | /// The path to the directory to be added to the zip archive, or updated in
|
---|
930 | /// the zip archive.
|
---|
931 | /// </param>
|
---|
932 | ///
|
---|
933 | /// <returns>
|
---|
934 | /// The <c>ZipEntry</c> corresponding to the Directory that was added or updated.
|
---|
935 | /// </returns>
|
---|
936 | public ZipEntry UpdateDirectory(string directoryName)
|
---|
937 | {
|
---|
938 | return UpdateDirectory(directoryName, null);
|
---|
939 | }
|
---|
940 |
|
---|
941 |
|
---|
942 | /// <summary>
|
---|
943 | /// Add or update a directory in the zip archive at the specified root
|
---|
944 | /// directory in the archive.
|
---|
945 | /// </summary>
|
---|
946 | ///
|
---|
947 | /// <remarks>
|
---|
948 | /// If the specified directory does not exist in the archive, then this method
|
---|
949 | /// is equivalent to calling <c>AddDirectory()</c>. If the specified
|
---|
950 | /// directory already exists in the archive, then this method updates any
|
---|
951 | /// existing entries, and adds any new entries. Any entries that are in the
|
---|
952 | /// zip archive but not in the specified directory, are left alone. In other
|
---|
953 | /// words, the contents of the zip file will be a union of the previous
|
---|
954 | /// contents and the new files.
|
---|
955 | /// </remarks>
|
---|
956 | ///
|
---|
957 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string,string)"/>
|
---|
958 | /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string,string)"/>
|
---|
959 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateItem(string,string)"/>
|
---|
960 | ///
|
---|
961 | /// <param name="directoryName">
|
---|
962 | /// The path to the directory to be added to the zip archive, or updated
|
---|
963 | /// in the zip archive.
|
---|
964 | /// </param>
|
---|
965 | ///
|
---|
966 | /// <param name="directoryPathInArchive">
|
---|
967 | /// Specifies a directory path to use to override any path in the
|
---|
968 | /// <c>directoryName</c>. This path may, or may not, correspond to a real
|
---|
969 | /// directory in the current filesystem. If the files within the zip are
|
---|
970 | /// later extracted, this is the path used for the extracted file. Passing
|
---|
971 | /// <c>null</c> (<c>Nothing</c> in VB) will use the path on the
|
---|
972 | /// <c>directoryName</c>, if any. Passing the empty string ("") will insert
|
---|
973 | /// the item at the root path within the archive.
|
---|
974 | /// </param>
|
---|
975 | ///
|
---|
976 | /// <returns>
|
---|
977 | /// The <c>ZipEntry</c> corresponding to the Directory that was added or updated.
|
---|
978 | /// </returns>
|
---|
979 | public ZipEntry UpdateDirectory(string directoryName, String directoryPathInArchive)
|
---|
980 | {
|
---|
981 | return this.AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOrUpdate);
|
---|
982 | }
|
---|
983 |
|
---|
984 |
|
---|
985 |
|
---|
986 |
|
---|
987 |
|
---|
988 | /// <summary>
|
---|
989 | /// Add or update a file or directory in the zip archive.
|
---|
990 | /// </summary>
|
---|
991 | ///
|
---|
992 | /// <remarks>
|
---|
993 | /// <para>
|
---|
994 | /// This is useful when the application is not sure or does not care if the
|
---|
995 | /// item to be added is a file or directory, and does not know or does not
|
---|
996 | /// care if the item already exists in the <c>ZipFile</c>. Calling this method
|
---|
997 | /// is equivalent to calling <c>RemoveEntry()</c> if an entry by the same name
|
---|
998 | /// already exists, followed calling by <c>AddItem()</c>.
|
---|
999 | /// </para>
|
---|
1000 | ///
|
---|
1001 | /// <para>
|
---|
1002 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1003 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1004 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1005 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1006 | /// respective values at the time of this call will be applied to the
|
---|
1007 | /// <c>ZipEntry</c> added.
|
---|
1008 | /// </para>
|
---|
1009 | /// </remarks>
|
---|
1010 | ///
|
---|
1011 | /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/>
|
---|
1012 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string)"/>
|
---|
1013 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/>
|
---|
1014 | ///
|
---|
1015 | /// <param name="itemName">
|
---|
1016 | /// the path to the file or directory to be added or updated.
|
---|
1017 | /// </param>
|
---|
1018 | public void UpdateItem(string itemName)
|
---|
1019 | {
|
---|
1020 | UpdateItem(itemName, null);
|
---|
1021 | }
|
---|
1022 |
|
---|
1023 |
|
---|
1024 | /// <summary>
|
---|
1025 | /// Add or update a file or directory.
|
---|
1026 | /// </summary>
|
---|
1027 | ///
|
---|
1028 | /// <remarks>
|
---|
1029 | /// <para>
|
---|
1030 | /// This method is useful when the application is not sure or does not care if
|
---|
1031 | /// the item to be added is a file or directory, and does not know or does not
|
---|
1032 | /// care if the item already exists in the <c>ZipFile</c>. Calling this method
|
---|
1033 | /// is equivalent to calling <c>RemoveEntry()</c>, if an entry by that name
|
---|
1034 | /// exists, and then calling <c>AddItem()</c>.
|
---|
1035 | /// </para>
|
---|
1036 | ///
|
---|
1037 | /// <para>
|
---|
1038 | /// This version of the method allows the caller to explicitly specify the
|
---|
1039 | /// directory path to be used for the item being added to the archive. The
|
---|
1040 | /// entry or entries that are added or updated will use the specified
|
---|
1041 | /// <c>DirectoryPathInArchive</c>. Extracting the entry from the archive will
|
---|
1042 | /// result in a file stored in that directory path.
|
---|
1043 | /// </para>
|
---|
1044 | ///
|
---|
1045 | /// <para>
|
---|
1046 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1047 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1048 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1049 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1050 | /// respective values at the time of this call will be applied to the
|
---|
1051 | /// <c>ZipEntry</c> added.
|
---|
1052 | /// </para>
|
---|
1053 | /// </remarks>
|
---|
1054 | ///
|
---|
1055 | /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string, string)"/>
|
---|
1056 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateFile(string, string)"/>
|
---|
1057 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string, string)"/>
|
---|
1058 | ///
|
---|
1059 | /// <param name="itemName">
|
---|
1060 | /// The path for the File or Directory to be added or updated.
|
---|
1061 | /// </param>
|
---|
1062 | /// <param name="directoryPathInArchive">
|
---|
1063 | /// Specifies a directory path to use to override any path in the
|
---|
1064 | /// <c>itemName</c>. This path may, or may not, correspond to a real
|
---|
1065 | /// directory in the current filesystem. If the files within the zip are
|
---|
1066 | /// later extracted, this is the path used for the extracted file. Passing
|
---|
1067 | /// <c>null</c> (<c>Nothing</c> in VB) will use the path on the
|
---|
1068 | /// <c>itemName</c>, if any. Passing the empty string ("") will insert the
|
---|
1069 | /// item at the root path within the archive.
|
---|
1070 | /// </param>
|
---|
1071 | public void UpdateItem(string itemName, string directoryPathInArchive)
|
---|
1072 | {
|
---|
1073 | if (File.Exists(itemName))
|
---|
1074 | UpdateFile(itemName, directoryPathInArchive);
|
---|
1075 |
|
---|
1076 | else if (Directory.Exists(itemName))
|
---|
1077 | UpdateDirectory(itemName, directoryPathInArchive);
|
---|
1078 |
|
---|
1079 | else
|
---|
1080 | throw new FileNotFoundException(String.Format("That file or directory ({0}) does not exist!", itemName));
|
---|
1081 | }
|
---|
1082 |
|
---|
1083 |
|
---|
1084 |
|
---|
1085 |
|
---|
1086 | /// <summary>
|
---|
1087 | /// Adds a named entry into the zip archive, taking content for the entry
|
---|
1088 | /// from a string.
|
---|
1089 | /// </summary>
|
---|
1090 | ///
|
---|
1091 | /// <remarks>
|
---|
1092 | /// Calling this method creates an entry using the given fileName and
|
---|
1093 | /// directory path within the archive. There is no need for a file by the
|
---|
1094 | /// given name to exist in the filesystem; the name is used within the zip
|
---|
1095 | /// archive only. The content for the entry is encoded using the default text
|
---|
1096 | /// encoding for the machine, or on Silverlight, using UTF-8.
|
---|
1097 | /// </remarks>
|
---|
1098 | ///
|
---|
1099 | /// <param name="content">
|
---|
1100 | /// The content of the file, should it be extracted from the zip.
|
---|
1101 | /// </param>
|
---|
1102 | ///
|
---|
1103 | /// <param name="entryName">
|
---|
1104 | /// The name, including any path, to use for the entry within the archive.
|
---|
1105 | /// </param>
|
---|
1106 | ///
|
---|
1107 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1108 | ///
|
---|
1109 | /// <example>
|
---|
1110 | ///
|
---|
1111 | /// This example shows how to add an entry to the zipfile, using a string as
|
---|
1112 | /// content for that entry.
|
---|
1113 | ///
|
---|
1114 | /// <code lang="C#">
|
---|
1115 | /// string Content = "This string will be the content of the Readme.txt file in the zip archive.";
|
---|
1116 | /// using (ZipFile zip1 = new ZipFile())
|
---|
1117 | /// {
|
---|
1118 | /// zip1.AddFile("MyDocuments\\Resume.doc", "files");
|
---|
1119 | /// zip1.AddEntry("Readme.txt", Content);
|
---|
1120 | /// zip1.Comment = "This zip file was created at " + System.DateTime.Now.ToString("G");
|
---|
1121 | /// zip1.Save("Content.zip");
|
---|
1122 | /// }
|
---|
1123 | ///
|
---|
1124 | /// </code>
|
---|
1125 | /// <code lang="VB">
|
---|
1126 | /// Public Sub Run()
|
---|
1127 | /// Dim Content As String = "This string will be the content of the Readme.txt file in the zip archive."
|
---|
1128 | /// Using zip1 As ZipFile = New ZipFile
|
---|
1129 | /// zip1.AddEntry("Readme.txt", Content)
|
---|
1130 | /// zip1.AddFile("MyDocuments\Resume.doc", "files")
|
---|
1131 | /// zip1.Comment = ("This zip file was created at " & DateTime.Now.ToString("G"))
|
---|
1132 | /// zip1.Save("Content.zip")
|
---|
1133 | /// End Using
|
---|
1134 | /// End Sub
|
---|
1135 | /// </code>
|
---|
1136 | /// </example>
|
---|
1137 | public ZipEntry AddEntry(string entryName, string content)
|
---|
1138 | {
|
---|
1139 | #if SILVERLIGHT
|
---|
1140 | return AddEntry(entryName, content, System.Text.Encoding.UTF8);
|
---|
1141 | #else
|
---|
1142 | return AddEntry(entryName, content, System.Text.Encoding.Default);
|
---|
1143 | #endif
|
---|
1144 | }
|
---|
1145 |
|
---|
1146 |
|
---|
1147 |
|
---|
1148 | /// <summary>
|
---|
1149 | /// Adds a named entry into the zip archive, taking content for the entry
|
---|
1150 | /// from a string, and using the specified text encoding.
|
---|
1151 | /// </summary>
|
---|
1152 | ///
|
---|
1153 | /// <remarks>
|
---|
1154 | ///
|
---|
1155 | /// <para>
|
---|
1156 | /// Calling this method creates an entry using the given fileName and
|
---|
1157 | /// directory path within the archive. There is no need for a file by the
|
---|
1158 | /// given name to exist in the filesystem; the name is used within the zip
|
---|
1159 | /// archive only.
|
---|
1160 | /// </para>
|
---|
1161 | ///
|
---|
1162 | /// <para>
|
---|
1163 | /// The content for the entry, a string value, is encoded using the given
|
---|
1164 | /// text encoding. A BOM (byte-order-mark) is emitted into the file, if the
|
---|
1165 | /// Encoding parameter is set for that.
|
---|
1166 | /// </para>
|
---|
1167 | ///
|
---|
1168 | /// <para>
|
---|
1169 | /// Most Encoding classes support a constructor that accepts a boolean,
|
---|
1170 | /// indicating whether to emit a BOM or not. For example see <see
|
---|
1171 | /// cref="System.Text.UTF8Encoding(bool)"/>.
|
---|
1172 | /// </para>
|
---|
1173 | ///
|
---|
1174 | /// </remarks>
|
---|
1175 | ///
|
---|
1176 | /// <param name="entryName">
|
---|
1177 | /// The name, including any path, to use within the archive for the entry.
|
---|
1178 | /// </param>
|
---|
1179 | ///
|
---|
1180 | /// <param name="content">
|
---|
1181 | /// The content of the file, should it be extracted from the zip.
|
---|
1182 | /// </param>
|
---|
1183 | ///
|
---|
1184 | /// <param name="encoding">
|
---|
1185 | /// The text encoding to use when encoding the string. Be aware: This is
|
---|
1186 | /// distinct from the text encoding used to encode the fileName, as specified
|
---|
1187 | /// in <see cref="ProvisionalAlternateEncoding" />.
|
---|
1188 | /// </param>
|
---|
1189 | ///
|
---|
1190 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1191 | ///
|
---|
1192 | public ZipEntry AddEntry(string entryName, string content, System.Text.Encoding encoding)
|
---|
1193 | {
|
---|
1194 | // cannot employ a using clause here. We need the stream to
|
---|
1195 | // persist after exit from this method.
|
---|
1196 | var ms = new MemoryStream();
|
---|
1197 |
|
---|
1198 | // cannot use a using clause here; StreamWriter takes
|
---|
1199 | // ownership of the stream and Disposes it before we are ready.
|
---|
1200 | var sw = new StreamWriter(ms, encoding);
|
---|
1201 | sw.Write(content);
|
---|
1202 | sw.Flush();
|
---|
1203 |
|
---|
1204 | // reset to allow reading later
|
---|
1205 | ms.Seek(0, SeekOrigin.Begin);
|
---|
1206 |
|
---|
1207 | return AddEntry(entryName, ms);
|
---|
1208 |
|
---|
1209 | // must not dispose the MemoryStream - it will be used later.
|
---|
1210 | }
|
---|
1211 |
|
---|
1212 |
|
---|
1213 | /// <summary>
|
---|
1214 | /// Create an entry in the <c>ZipFile</c> using the given <c>Stream</c>
|
---|
1215 | /// as input. The entry will have the given filename.
|
---|
1216 | /// </summary>
|
---|
1217 | ///
|
---|
1218 | /// <remarks>
|
---|
1219 | ///
|
---|
1220 | /// <para>
|
---|
1221 | /// The application should provide an open, readable stream; in this case it
|
---|
1222 | /// will be read during the call to <see cref="ZipFile.Save()"/> or one of
|
---|
1223 | /// its overloads.
|
---|
1224 | /// </para>
|
---|
1225 | ///
|
---|
1226 | /// <para>
|
---|
1227 | /// The passed stream will be read from its current position. If
|
---|
1228 | /// necessary, callers should set the position in the stream before
|
---|
1229 | /// calling AddEntry(). This might be appropriate when using this method
|
---|
1230 | /// with a MemoryStream, for example.
|
---|
1231 | /// </para>
|
---|
1232 | ///
|
---|
1233 | /// <para>
|
---|
1234 | /// In cases where a large number of streams will be added to the
|
---|
1235 | /// <c>ZipFile</c>, the application may wish to avoid maintaining all of the
|
---|
1236 | /// streams open simultaneously. To handle this situation, the application
|
---|
1237 | /// should use the <see cref="AddEntry(string, OpenDelegate, CloseDelegate)"/>
|
---|
1238 | /// overload.
|
---|
1239 | /// </para>
|
---|
1240 | ///
|
---|
1241 | /// <para>
|
---|
1242 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1243 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1244 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1245 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1246 | /// respective values at the time of this call will be applied to the
|
---|
1247 | /// <c>ZipEntry</c> added.
|
---|
1248 | /// </para>
|
---|
1249 | ///
|
---|
1250 | /// </remarks>
|
---|
1251 | ///
|
---|
1252 | /// <example>
|
---|
1253 | /// <para>
|
---|
1254 | /// This example adds a single entry to a <c>ZipFile</c> via a <c>Stream</c>.
|
---|
1255 | /// </para>
|
---|
1256 | ///
|
---|
1257 | /// <code lang="C#">
|
---|
1258 | /// String zipToCreate = "Content.zip";
|
---|
1259 | /// String fileNameInArchive = "Content-From-Stream.bin";
|
---|
1260 | /// using (System.IO.Stream streamToRead = MyStreamOpener())
|
---|
1261 | /// {
|
---|
1262 | /// using (ZipFile zip = new ZipFile())
|
---|
1263 | /// {
|
---|
1264 | /// ZipEntry entry= zip.AddEntry(fileNameInArchive, streamToRead);
|
---|
1265 | /// zip.AddFile("Readme.txt");
|
---|
1266 | /// zip.Save(zipToCreate); // the stream is read implicitly here
|
---|
1267 | /// }
|
---|
1268 | /// }
|
---|
1269 | /// </code>
|
---|
1270 | ///
|
---|
1271 | /// <code lang="VB">
|
---|
1272 | /// Dim zipToCreate As String = "Content.zip"
|
---|
1273 | /// Dim fileNameInArchive As String = "Content-From-Stream.bin"
|
---|
1274 | /// Using streamToRead as System.IO.Stream = MyStreamOpener()
|
---|
1275 | /// Using zip As ZipFile = New ZipFile()
|
---|
1276 | /// Dim entry as ZipEntry = zip.AddEntry(fileNameInArchive, streamToRead)
|
---|
1277 | /// zip.AddFile("Readme.txt")
|
---|
1278 | /// zip.Save(zipToCreate) '' the stream is read implicitly, here
|
---|
1279 | /// End Using
|
---|
1280 | /// End Using
|
---|
1281 | /// </code>
|
---|
1282 | /// </example>
|
---|
1283 | ///
|
---|
1284 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateEntry(string, System.IO.Stream)"/>
|
---|
1285 | ///
|
---|
1286 | /// <param name="entryName">
|
---|
1287 | /// The name, including any path, which is shown in the zip file for the added
|
---|
1288 | /// entry.
|
---|
1289 | /// </param>
|
---|
1290 | /// <param name="stream">
|
---|
1291 | /// The input stream from which to grab content for the file
|
---|
1292 | /// </param>
|
---|
1293 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1294 | public ZipEntry AddEntry(string entryName, Stream stream)
|
---|
1295 | {
|
---|
1296 | ZipEntry ze = ZipEntry.CreateForStream(entryName, stream);
|
---|
1297 | ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now);
|
---|
1298 | if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName);
|
---|
1299 | return _InternalAddEntry(ze);
|
---|
1300 | }
|
---|
1301 |
|
---|
1302 |
|
---|
1303 |
|
---|
1304 | /// <summary>
|
---|
1305 | /// Add a ZipEntry for which content is written directly by the application.
|
---|
1306 | /// </summary>
|
---|
1307 | ///
|
---|
1308 | /// <remarks>
|
---|
1309 | /// <para>
|
---|
1310 | /// When the application needs to write the zip entry data, use this
|
---|
1311 | /// method to add the ZipEntry. For example, in the case that the
|
---|
1312 | /// application wishes to write the XML representation of a DataSet into
|
---|
1313 | /// a ZipEntry, the application can use this method to do so.
|
---|
1314 | /// </para>
|
---|
1315 | ///
|
---|
1316 | /// <para>
|
---|
1317 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1318 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1319 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1320 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1321 | /// respective values at the time of this call will be applied to the
|
---|
1322 | /// <c>ZipEntry</c> added.
|
---|
1323 | /// </para>
|
---|
1324 | ///
|
---|
1325 | /// <para>
|
---|
1326 | /// About progress events: When using the WriteDelegate, DotNetZip does
|
---|
1327 | /// not issue any SaveProgress events with <c>EventType</c> = <see
|
---|
1328 | /// cref="ZipProgressEventType.Saving_EntryBytesRead">
|
---|
1329 | /// Saving_EntryBytesRead</see>. (This is because it is the
|
---|
1330 | /// application's code that runs in WriteDelegate - there's no way for
|
---|
1331 | /// DotNetZip to know when to issue a EntryBytesRead event.)
|
---|
1332 | /// Applications that want to update a progress bar or similar status
|
---|
1333 | /// indicator should do so from within the WriteDelegate
|
---|
1334 | /// itself. DotNetZip will issue the other SaveProgress events,
|
---|
1335 | /// including <see cref="ZipProgressEventType.Saving_Started">
|
---|
1336 | /// Saving_Started</see>,
|
---|
1337 | /// <see cref="ZipProgressEventType.Saving_BeforeWriteEntry">
|
---|
1338 | /// Saving_BeforeWriteEntry</see>, and <see
|
---|
1339 | /// cref="ZipProgressEventType.Saving_AfterWriteEntry">
|
---|
1340 | /// Saving_AfterWriteEntry</see>.
|
---|
1341 | /// </para>
|
---|
1342 | ///
|
---|
1343 | /// <para>
|
---|
1344 | /// Note: When you use PKZip encryption, it's normally necessary to
|
---|
1345 | /// compute the CRC of the content to be encrypted, before compressing or
|
---|
1346 | /// encrypting it. Therefore, when using PKZip encryption with a
|
---|
1347 | /// WriteDelegate, the WriteDelegate CAN BE called twice: once to compute
|
---|
1348 | /// the CRC, and the second time to potentially compress and
|
---|
1349 | /// encrypt. Surprising, but true. This is because PKWARE specified that
|
---|
1350 | /// the encryption initialization data depends on the CRC.
|
---|
1351 | /// If this happens, for each call of the delegate, your
|
---|
1352 | /// application must stream the same entry data in its entirety. If your
|
---|
1353 | /// application writes different data during the second call, it will
|
---|
1354 | /// result in a corrupt zip file.
|
---|
1355 | /// </para>
|
---|
1356 | ///
|
---|
1357 | /// <para>
|
---|
1358 | /// The double-read behavior happens with all types of entries, not only
|
---|
1359 | /// those that use WriteDelegate. It happens if you add an entry from a
|
---|
1360 | /// filesystem file, or using a string, or a stream, or an opener/closer
|
---|
1361 | /// pair. But in those cases, DotNetZip takes care of reading twice; in
|
---|
1362 | /// the case of the WriteDelegate, the application code gets invoked
|
---|
1363 | /// twice. Be aware.
|
---|
1364 | /// </para>
|
---|
1365 | ///
|
---|
1366 | /// <para>
|
---|
1367 | /// As you can imagine, this can cause performance problems for large
|
---|
1368 | /// streams, and it can lead to correctness problems when you use a
|
---|
1369 | /// <c>WriteDelegate</c>. This is a pretty big pitfall. There are two
|
---|
1370 | /// ways to avoid it. First, and most preferred: don't use PKZIP
|
---|
1371 | /// encryption. If you use the WinZip AES encryption, this problem
|
---|
1372 | /// doesn't occur, because the encryption protocol doesn't require the CRC
|
---|
1373 | /// up front. Second: if you do choose to use PKZIP encryption, write out
|
---|
1374 | /// to a non-seekable stream (like standard output, or the
|
---|
1375 | /// Response.OutputStream in an ASP.NET application). In this case,
|
---|
1376 | /// DotNetZip will use an alternative encryption protocol that does not
|
---|
1377 | /// rely on the CRC of the content. This also implies setting bit 3 in
|
---|
1378 | /// the zip entry, which still presents problems for some zip tools.
|
---|
1379 | /// </para>
|
---|
1380 | ///
|
---|
1381 | /// <para>
|
---|
1382 | /// In the future I may modify DotNetZip to *always* use bit 3 when PKZIP
|
---|
1383 | /// encryption is in use. This seems like a win overall, but there will
|
---|
1384 | /// be some work involved. If you feel strongly about it, visit the
|
---|
1385 | /// DotNetZip forums and vote up <see
|
---|
1386 | /// href="http://dotnetzip.codeplex.com/workitem/13686">the Workitem
|
---|
1387 | /// tracking this issue</see>.
|
---|
1388 | /// </para>
|
---|
1389 | ///
|
---|
1390 | /// </remarks>
|
---|
1391 | ///
|
---|
1392 | /// <param name="entryName">the name of the entry to add</param>
|
---|
1393 | /// <param name="writer">the delegate which will write the entry content</param>
|
---|
1394 | /// <returns>the ZipEntry added</returns>
|
---|
1395 | ///
|
---|
1396 | /// <example>
|
---|
1397 | ///
|
---|
1398 | /// This example shows an application filling a DataSet, then saving the
|
---|
1399 | /// contents of that DataSet as XML, into a ZipEntry in a ZipFile, using an
|
---|
1400 | /// anonymous delegate in C#. The DataSet XML is never saved to a disk file.
|
---|
1401 | ///
|
---|
1402 | /// <code lang="C#">
|
---|
1403 | /// var c1= new System.Data.SqlClient.SqlConnection(connstring1);
|
---|
1404 | /// var da = new System.Data.SqlClient.SqlDataAdapter()
|
---|
1405 | /// {
|
---|
1406 | /// SelectCommand= new System.Data.SqlClient.SqlCommand(strSelect, c1)
|
---|
1407 | /// };
|
---|
1408 | ///
|
---|
1409 | /// DataSet ds1 = new DataSet();
|
---|
1410 | /// da.Fill(ds1, "Invoices");
|
---|
1411 | ///
|
---|
1412 | /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
|
---|
1413 | /// {
|
---|
1414 | /// zip.AddEntry(zipEntryName, (name,stream) => ds1.WriteXml(stream) );
|
---|
1415 | /// zip.Save(zipFileName);
|
---|
1416 | /// }
|
---|
1417 | /// </code>
|
---|
1418 | /// </example>
|
---|
1419 | ///
|
---|
1420 | /// <example>
|
---|
1421 | ///
|
---|
1422 | /// This example uses an anonymous method in C# as the WriteDelegate to provide
|
---|
1423 | /// the data for the ZipEntry. The example is a bit contrived - the
|
---|
1424 | /// <c>AddFile()</c> method is a simpler way to insert the contents of a file
|
---|
1425 | /// into an entry in a zip file. On the other hand, if there is some sort of
|
---|
1426 | /// processing or transformation of the file contents required before writing,
|
---|
1427 | /// the application could use the <c>WriteDelegate</c> to do it, in this way.
|
---|
1428 | ///
|
---|
1429 | /// <code lang="C#">
|
---|
1430 | /// using (var input = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ))
|
---|
1431 | /// {
|
---|
1432 | /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
|
---|
1433 | /// {
|
---|
1434 | /// zip.AddEntry(zipEntryName, (name,output) =>
|
---|
1435 | /// {
|
---|
1436 | /// byte[] buffer = new byte[BufferSize];
|
---|
1437 | /// int n;
|
---|
1438 | /// while ((n = input.Read(buffer, 0, buffer.Length)) != 0)
|
---|
1439 | /// {
|
---|
1440 | /// // could transform the data here...
|
---|
1441 | /// output.Write(buffer, 0, n);
|
---|
1442 | /// // could update a progress bar here
|
---|
1443 | /// }
|
---|
1444 | /// });
|
---|
1445 | ///
|
---|
1446 | /// zip.Save(zipFileName);
|
---|
1447 | /// }
|
---|
1448 | /// }
|
---|
1449 | /// </code>
|
---|
1450 | /// </example>
|
---|
1451 | ///
|
---|
1452 | /// <example>
|
---|
1453 | ///
|
---|
1454 | /// This example uses a named delegate in VB to write data for the given
|
---|
1455 | /// ZipEntry (VB9 does not have anonymous delegates). The example here is a bit
|
---|
1456 | /// contrived - a simpler way to add the contents of a file to a ZipEntry is to
|
---|
1457 | /// simply use the appropriate <c>AddFile()</c> method. The key scenario for
|
---|
1458 | /// which the <c>WriteDelegate</c> makes sense is saving a DataSet, in XML
|
---|
1459 | /// format, to the zip file. The DataSet can write XML to a stream, and the
|
---|
1460 | /// WriteDelegate is the perfect place to write into the zip file. There may be
|
---|
1461 | /// other data structures that can write to a stream, but cannot be read as a
|
---|
1462 | /// stream. The <c>WriteDelegate</c> would be appropriate for those cases as
|
---|
1463 | /// well.
|
---|
1464 | ///
|
---|
1465 | /// <code lang="VB">
|
---|
1466 | /// Private Sub WriteEntry (ByVal name As String, ByVal output As Stream)
|
---|
1467 | /// Using input As FileStream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
|
---|
1468 | /// Dim n As Integer = -1
|
---|
1469 | /// Dim buffer As Byte() = New Byte(BufferSize){}
|
---|
1470 | /// Do While n <> 0
|
---|
1471 | /// n = input.Read(buffer, 0, buffer.Length)
|
---|
1472 | /// output.Write(buffer, 0, n)
|
---|
1473 | /// Loop
|
---|
1474 | /// End Using
|
---|
1475 | /// End Sub
|
---|
1476 | ///
|
---|
1477 | /// Public Sub Run()
|
---|
1478 | /// Using zip = New ZipFile
|
---|
1479 | /// zip.AddEntry(zipEntryName, New WriteDelegate(AddressOf WriteEntry))
|
---|
1480 | /// zip.Save(zipFileName)
|
---|
1481 | /// End Using
|
---|
1482 | /// End Sub
|
---|
1483 | /// </code>
|
---|
1484 | /// </example>
|
---|
1485 | public ZipEntry AddEntry(string entryName, WriteDelegate writer)
|
---|
1486 | {
|
---|
1487 | ZipEntry ze = ZipEntry.CreateForWriter(entryName, writer);
|
---|
1488 | if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName);
|
---|
1489 | return _InternalAddEntry(ze);
|
---|
1490 | }
|
---|
1491 |
|
---|
1492 |
|
---|
1493 | /// <summary>
|
---|
1494 | /// Add an entry, for which the application will provide a stream
|
---|
1495 | /// containing the entry data, on a just-in-time basis.
|
---|
1496 | /// </summary>
|
---|
1497 | ///
|
---|
1498 | /// <remarks>
|
---|
1499 | /// <para>
|
---|
1500 | /// In cases where the application wishes to open the stream that
|
---|
1501 | /// holds the content for the ZipEntry, on a just-in-time basis, the
|
---|
1502 | /// application can use this method. The application provides an
|
---|
1503 | /// opener delegate that will be called by the DotNetZip library to
|
---|
1504 | /// obtain a readable stream that can be read to get the bytes for
|
---|
1505 | /// the given entry. Typically, this delegate opens a stream.
|
---|
1506 | /// Optionally, the application can provide a closer delegate as
|
---|
1507 | /// well, which will be called by DotNetZip when all bytes have been
|
---|
1508 | /// read from the entry.
|
---|
1509 | /// </para>
|
---|
1510 | ///
|
---|
1511 | /// <para>
|
---|
1512 | /// These delegates are called from within the scope of the call to
|
---|
1513 | /// ZipFile.Save().
|
---|
1514 | /// </para>
|
---|
1515 | ///
|
---|
1516 | /// <para>
|
---|
1517 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1518 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1519 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1520 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1521 | /// respective values at the time of this call will be applied to the
|
---|
1522 | /// <c>ZipEntry</c> added.
|
---|
1523 | /// </para>
|
---|
1524 | ///
|
---|
1525 | /// </remarks>
|
---|
1526 | ///
|
---|
1527 | /// <example>
|
---|
1528 | ///
|
---|
1529 | /// This example uses anonymous methods in C# to open and close the
|
---|
1530 | /// source stream for the content for a zip entry.
|
---|
1531 | ///
|
---|
1532 | /// <code lang="C#">
|
---|
1533 | /// using(Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
|
---|
1534 | /// {
|
---|
1535 | /// zip.AddEntry(zipEntryName,
|
---|
1536 | /// (name) => File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ),
|
---|
1537 | /// (name, stream) => stream.Close()
|
---|
1538 | /// );
|
---|
1539 | ///
|
---|
1540 | /// zip.Save(zipFileName);
|
---|
1541 | /// }
|
---|
1542 | /// </code>
|
---|
1543 | ///
|
---|
1544 | /// </example>
|
---|
1545 | ///
|
---|
1546 | /// <example>
|
---|
1547 | ///
|
---|
1548 | /// This example uses delegates in VB.NET to open and close the
|
---|
1549 | /// the source stream for the content for a zip entry. VB 9.0 lacks
|
---|
1550 | /// support for "Sub" lambda expressions, and so the CloseDelegate must
|
---|
1551 | /// be an actual, named Sub.
|
---|
1552 | ///
|
---|
1553 | /// <code lang="VB">
|
---|
1554 | ///
|
---|
1555 | /// Function MyStreamOpener(ByVal entryName As String) As Stream
|
---|
1556 | /// '' This simply opens a file. You probably want to do somethinig
|
---|
1557 | /// '' more involved here: open a stream to read from a database,
|
---|
1558 | /// '' open a stream on an HTTP connection, and so on.
|
---|
1559 | /// Return File.OpenRead(entryName)
|
---|
1560 | /// End Function
|
---|
1561 | ///
|
---|
1562 | /// Sub MyStreamCloser(entryName As String, stream As Stream)
|
---|
1563 | /// stream.Close()
|
---|
1564 | /// End Sub
|
---|
1565 | ///
|
---|
1566 | /// Public Sub Run()
|
---|
1567 | /// Dim dirToZip As String = "fodder"
|
---|
1568 | /// Dim zipFileToCreate As String = "Archive.zip"
|
---|
1569 | /// Dim opener As OpenDelegate = AddressOf MyStreamOpener
|
---|
1570 | /// Dim closer As CloseDelegate = AddressOf MyStreamCloser
|
---|
1571 | /// Dim numFilestoAdd As Int32 = 4
|
---|
1572 | /// Using zip As ZipFile = New ZipFile
|
---|
1573 | /// Dim i As Integer
|
---|
1574 | /// For i = 0 To numFilesToAdd - 1
|
---|
1575 | /// zip.AddEntry(String.Format("content-{0:000}.txt"), opener, closer)
|
---|
1576 | /// Next i
|
---|
1577 | /// zip.Save(zipFileToCreate)
|
---|
1578 | /// End Using
|
---|
1579 | /// End Sub
|
---|
1580 | ///
|
---|
1581 | /// </code>
|
---|
1582 | /// </example>
|
---|
1583 | ///
|
---|
1584 | /// <param name="entryName">the name of the entry to add</param>
|
---|
1585 | /// <param name="opener">
|
---|
1586 | /// the delegate that will be invoked by ZipFile.Save() to get the
|
---|
1587 | /// readable stream for the given entry. ZipFile.Save() will call
|
---|
1588 | /// read on this stream to obtain the data for the entry. This data
|
---|
1589 | /// will then be compressed and written to the newly created zip
|
---|
1590 | /// file.
|
---|
1591 | /// </param>
|
---|
1592 | /// <param name="closer">
|
---|
1593 | /// the delegate that will be invoked to close the stream. This may
|
---|
1594 | /// be null (Nothing in VB), in which case no call is makde to close
|
---|
1595 | /// the stream.
|
---|
1596 | /// </param>
|
---|
1597 | /// <returns>the ZipEntry added</returns>
|
---|
1598 | ///
|
---|
1599 | public ZipEntry AddEntry(string entryName, OpenDelegate opener, CloseDelegate closer)
|
---|
1600 | {
|
---|
1601 | ZipEntry ze = ZipEntry.CreateForJitStreamProvider(entryName, opener, closer);
|
---|
1602 | ze.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now);
|
---|
1603 | if (Verbose) StatusMessageTextWriter.WriteLine("adding {0}...", entryName);
|
---|
1604 | return _InternalAddEntry(ze);
|
---|
1605 | }
|
---|
1606 |
|
---|
1607 |
|
---|
1608 |
|
---|
1609 | private ZipEntry _InternalAddEntry(ZipEntry ze)
|
---|
1610 | {
|
---|
1611 | // stamp all the props onto the entry
|
---|
1612 | ze._container = new ZipContainer(this);
|
---|
1613 | ze.CompressionMethod = this.CompressionMethod;
|
---|
1614 | ze.CompressionLevel = this.CompressionLevel;
|
---|
1615 | ze.ExtractExistingFile = this.ExtractExistingFile;
|
---|
1616 | ze.ZipErrorAction = this.ZipErrorAction;
|
---|
1617 | ze.SetCompression = this.SetCompression;
|
---|
1618 | ze.AlternateEncoding = this.AlternateEncoding;
|
---|
1619 | ze.AlternateEncodingUsage = this.AlternateEncodingUsage;
|
---|
1620 | ze.Password = this._Password;
|
---|
1621 | ze.Encryption = this.Encryption;
|
---|
1622 | ze.EmitTimesInWindowsFormatWhenSaving = this._emitNtfsTimes;
|
---|
1623 | ze.EmitTimesInUnixFormatWhenSaving = this._emitUnixTimes;
|
---|
1624 | //string key = DictionaryKeyForEntry(ze);
|
---|
1625 | InternalAddEntry(ze.FileName,ze);
|
---|
1626 | AfterAddEntry(ze);
|
---|
1627 | return ze;
|
---|
1628 | }
|
---|
1629 |
|
---|
1630 |
|
---|
1631 |
|
---|
1632 |
|
---|
1633 | /// <summary>
|
---|
1634 | /// Updates the given entry in the <c>ZipFile</c>, using the given
|
---|
1635 | /// string as content for the <c>ZipEntry</c>.
|
---|
1636 | /// </summary>
|
---|
1637 | ///
|
---|
1638 | /// <remarks>
|
---|
1639 | ///
|
---|
1640 | /// <para>
|
---|
1641 | /// Calling this method is equivalent to removing the <c>ZipEntry</c> for
|
---|
1642 | /// the given file name and directory path, if it exists, and then calling
|
---|
1643 | /// <see cref="AddEntry(String,String)" />. See the documentation for
|
---|
1644 | /// that method for further explanation. The string content is encoded
|
---|
1645 | /// using the default encoding for the machine, or on Silverlight, using
|
---|
1646 | /// UTF-8. This encoding is distinct from the encoding used for the
|
---|
1647 | /// filename itself. See <see cref="AlternateEncoding"/>.
|
---|
1648 | /// </para>
|
---|
1649 | ///
|
---|
1650 | /// </remarks>
|
---|
1651 | ///
|
---|
1652 | /// <param name="entryName">
|
---|
1653 | /// The name, including any path, to use within the archive for the entry.
|
---|
1654 | /// </param>
|
---|
1655 | ///
|
---|
1656 | /// <param name="content">
|
---|
1657 | /// The content of the file, should it be extracted from the zip.
|
---|
1658 | /// </param>
|
---|
1659 | ///
|
---|
1660 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1661 | ///
|
---|
1662 | public ZipEntry UpdateEntry(string entryName, string content)
|
---|
1663 | {
|
---|
1664 | #if SILVERLIGHT
|
---|
1665 | return UpdateEntry(entryName, content, System.Text.Encoding.UTF8);
|
---|
1666 | #else
|
---|
1667 | return UpdateEntry(entryName, content, System.Text.Encoding.Default);
|
---|
1668 | #endif
|
---|
1669 | }
|
---|
1670 |
|
---|
1671 |
|
---|
1672 | /// <summary>
|
---|
1673 | /// Updates the given entry in the <c>ZipFile</c>, using the given string as
|
---|
1674 | /// content for the <c>ZipEntry</c>.
|
---|
1675 | /// </summary>
|
---|
1676 | ///
|
---|
1677 | /// <remarks>
|
---|
1678 | /// Calling this method is equivalent to removing the <c>ZipEntry</c> for the
|
---|
1679 | /// given file name and directory path, if it exists, and then calling <see
|
---|
1680 | /// cref="AddEntry(String,String, System.Text.Encoding)" />. See the
|
---|
1681 | /// documentation for that method for further explanation.
|
---|
1682 | /// </remarks>
|
---|
1683 | ///
|
---|
1684 | /// <param name="entryName">
|
---|
1685 | /// The name, including any path, to use within the archive for the entry.
|
---|
1686 | /// </param>
|
---|
1687 | ///
|
---|
1688 | /// <param name="content">
|
---|
1689 | /// The content of the file, should it be extracted from the zip.
|
---|
1690 | /// </param>
|
---|
1691 | ///
|
---|
1692 | /// <param name="encoding">
|
---|
1693 | /// The text encoding to use when encoding the string. Be aware: This is
|
---|
1694 | /// distinct from the text encoding used to encode the filename. See <see
|
---|
1695 | /// cref="AlternateEncoding" />.
|
---|
1696 | /// </param>
|
---|
1697 | ///
|
---|
1698 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1699 | ///
|
---|
1700 | public ZipEntry UpdateEntry(string entryName, string content, System.Text.Encoding encoding)
|
---|
1701 | {
|
---|
1702 | RemoveEntryForUpdate(entryName);
|
---|
1703 | return AddEntry(entryName, content, encoding);
|
---|
1704 | }
|
---|
1705 |
|
---|
1706 |
|
---|
1707 |
|
---|
1708 | /// <summary>
|
---|
1709 | /// Updates the given entry in the <c>ZipFile</c>, using the given delegate
|
---|
1710 | /// as the source for content for the <c>ZipEntry</c>.
|
---|
1711 | /// </summary>
|
---|
1712 | ///
|
---|
1713 | /// <remarks>
|
---|
1714 | /// Calling this method is equivalent to removing the <c>ZipEntry</c> for the
|
---|
1715 | /// given file name and directory path, if it exists, and then calling <see
|
---|
1716 | /// cref="AddEntry(String,WriteDelegate)" />. See the
|
---|
1717 | /// documentation for that method for further explanation.
|
---|
1718 | /// </remarks>
|
---|
1719 | ///
|
---|
1720 | /// <param name="entryName">
|
---|
1721 | /// The name, including any path, to use within the archive for the entry.
|
---|
1722 | /// </param>
|
---|
1723 | ///
|
---|
1724 | /// <param name="writer">the delegate which will write the entry content.</param>
|
---|
1725 | ///
|
---|
1726 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1727 | ///
|
---|
1728 | public ZipEntry UpdateEntry(string entryName, WriteDelegate writer)
|
---|
1729 | {
|
---|
1730 | RemoveEntryForUpdate(entryName);
|
---|
1731 | return AddEntry(entryName, writer);
|
---|
1732 | }
|
---|
1733 |
|
---|
1734 |
|
---|
1735 |
|
---|
1736 | /// <summary>
|
---|
1737 | /// Updates the given entry in the <c>ZipFile</c>, using the given delegates
|
---|
1738 | /// to open and close the stream that provides the content for the <c>ZipEntry</c>.
|
---|
1739 | /// </summary>
|
---|
1740 | ///
|
---|
1741 | /// <remarks>
|
---|
1742 | /// Calling this method is equivalent to removing the <c>ZipEntry</c> for the
|
---|
1743 | /// given file name and directory path, if it exists, and then calling <see
|
---|
1744 | /// cref="AddEntry(String,OpenDelegate, CloseDelegate)" />. See the
|
---|
1745 | /// documentation for that method for further explanation.
|
---|
1746 | /// </remarks>
|
---|
1747 | ///
|
---|
1748 | /// <param name="entryName">
|
---|
1749 | /// The name, including any path, to use within the archive for the entry.
|
---|
1750 | /// </param>
|
---|
1751 | ///
|
---|
1752 | /// <param name="opener">
|
---|
1753 | /// the delegate that will be invoked to open the stream
|
---|
1754 | /// </param>
|
---|
1755 | /// <param name="closer">
|
---|
1756 | /// the delegate that will be invoked to close the stream
|
---|
1757 | /// </param>
|
---|
1758 | ///
|
---|
1759 | /// <returns>The <c>ZipEntry</c> added or updated.</returns>
|
---|
1760 | ///
|
---|
1761 | public ZipEntry UpdateEntry(string entryName, OpenDelegate opener, CloseDelegate closer)
|
---|
1762 | {
|
---|
1763 | RemoveEntryForUpdate(entryName);
|
---|
1764 | return AddEntry(entryName, opener, closer);
|
---|
1765 | }
|
---|
1766 |
|
---|
1767 |
|
---|
1768 | /// <summary>
|
---|
1769 | /// Updates the given entry in the <c>ZipFile</c>, using the given stream as
|
---|
1770 | /// input, and the given filename and given directory Path.
|
---|
1771 | /// </summary>
|
---|
1772 | ///
|
---|
1773 | /// <remarks>
|
---|
1774 | /// <para>
|
---|
1775 | /// Calling the method is equivalent to calling <c>RemoveEntry()</c> if an
|
---|
1776 | /// entry by the same name already exists, and then calling <c>AddEntry()</c>
|
---|
1777 | /// with the given <c>fileName</c> and stream.
|
---|
1778 | /// </para>
|
---|
1779 | ///
|
---|
1780 | /// <para>
|
---|
1781 | /// The stream must be open and readable during the call to
|
---|
1782 | /// <c>ZipFile.Save</c>. You can dispense the stream on a just-in-time basis
|
---|
1783 | /// using the <see cref="ZipEntry.InputStream"/> property. Check the
|
---|
1784 | /// documentation of that property for more information.
|
---|
1785 | /// </para>
|
---|
1786 | ///
|
---|
1787 | /// <para>
|
---|
1788 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1789 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1790 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1791 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1792 | /// respective values at the time of this call will be applied to the
|
---|
1793 | /// <c>ZipEntry</c> added.
|
---|
1794 | /// </para>
|
---|
1795 | ///
|
---|
1796 | /// </remarks>
|
---|
1797 | ///
|
---|
1798 | /// <seealso cref="Ionic.Zip.ZipFile.AddEntry(string, System.IO.Stream)"/>
|
---|
1799 | /// <seealso cref="ZipEntry.InputStream"/>
|
---|
1800 | ///
|
---|
1801 | /// <param name="entryName">
|
---|
1802 | /// The name, including any path, to use within the archive for the entry.
|
---|
1803 | /// </param>
|
---|
1804 | ///
|
---|
1805 | /// <param name="stream">The input stream from which to read file data.</param>
|
---|
1806 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1807 | public ZipEntry UpdateEntry(string entryName, Stream stream)
|
---|
1808 | {
|
---|
1809 | RemoveEntryForUpdate(entryName);
|
---|
1810 | return AddEntry(entryName, stream);
|
---|
1811 | }
|
---|
1812 |
|
---|
1813 |
|
---|
1814 | private void RemoveEntryForUpdate(string entryName)
|
---|
1815 | {
|
---|
1816 | if (String.IsNullOrEmpty(entryName))
|
---|
1817 | throw new ArgumentNullException("entryName");
|
---|
1818 |
|
---|
1819 | string directoryPathInArchive = null;
|
---|
1820 | if (entryName.IndexOf('\\') != -1)
|
---|
1821 | {
|
---|
1822 | directoryPathInArchive = Path.GetDirectoryName(entryName);
|
---|
1823 | entryName = Path.GetFileName(entryName);
|
---|
1824 | }
|
---|
1825 | var key = ZipEntry.NameInArchive(entryName, directoryPathInArchive);
|
---|
1826 | if (this[key] != null)
|
---|
1827 | this.RemoveEntry(key);
|
---|
1828 | }
|
---|
1829 |
|
---|
1830 |
|
---|
1831 |
|
---|
1832 |
|
---|
1833 | /// <summary>
|
---|
1834 | /// Add an entry into the zip archive using the given filename and
|
---|
1835 | /// directory path within the archive, and the given content for the
|
---|
1836 | /// file. No file is created in the filesystem.
|
---|
1837 | /// </summary>
|
---|
1838 | ///
|
---|
1839 | /// <param name="byteContent">The data to use for the entry.</param>
|
---|
1840 | ///
|
---|
1841 | /// <param name="entryName">
|
---|
1842 | /// The name, including any path, to use within the archive for the entry.
|
---|
1843 | /// </param>
|
---|
1844 | ///
|
---|
1845 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1846 | public ZipEntry AddEntry(string entryName, byte[] byteContent)
|
---|
1847 | {
|
---|
1848 | if (byteContent == null) throw new ArgumentException("bad argument", "byteContent");
|
---|
1849 | var ms = new MemoryStream(byteContent);
|
---|
1850 | return AddEntry(entryName, ms);
|
---|
1851 | }
|
---|
1852 |
|
---|
1853 |
|
---|
1854 | /// <summary>
|
---|
1855 | /// Updates the given entry in the <c>ZipFile</c>, using the given byte
|
---|
1856 | /// array as content for the entry.
|
---|
1857 | /// </summary>
|
---|
1858 | ///
|
---|
1859 | /// <remarks>
|
---|
1860 | /// Calling this method is equivalent to removing the <c>ZipEntry</c>
|
---|
1861 | /// for the given filename and directory path, if it exists, and then
|
---|
1862 | /// calling <see cref="AddEntry(String,byte[])" />. See the
|
---|
1863 | /// documentation for that method for further explanation.
|
---|
1864 | /// </remarks>
|
---|
1865 | ///
|
---|
1866 | /// <param name="entryName">
|
---|
1867 | /// The name, including any path, to use within the archive for the entry.
|
---|
1868 | /// </param>
|
---|
1869 | ///
|
---|
1870 | /// <param name="byteContent">The content to use for the <c>ZipEntry</c>.</param>
|
---|
1871 | ///
|
---|
1872 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1873 | ///
|
---|
1874 | public ZipEntry UpdateEntry(string entryName, byte[] byteContent)
|
---|
1875 | {
|
---|
1876 | RemoveEntryForUpdate(entryName);
|
---|
1877 | return AddEntry(entryName, byteContent);
|
---|
1878 | }
|
---|
1879 |
|
---|
1880 |
|
---|
1881 | // private string DictionaryKeyForEntry(ZipEntry ze1)
|
---|
1882 | // {
|
---|
1883 | // var filename = SharedUtilities.NormalizePathForUseInZipFile(ze1.FileName);
|
---|
1884 | // return filename;
|
---|
1885 | // }
|
---|
1886 |
|
---|
1887 |
|
---|
1888 | /// <summary>
|
---|
1889 | /// Adds the contents of a filesystem directory to a Zip file archive.
|
---|
1890 | /// </summary>
|
---|
1891 | ///
|
---|
1892 | /// <remarks>
|
---|
1893 | ///
|
---|
1894 | /// <para>
|
---|
1895 | /// The name of the directory may be a relative path or a fully-qualified
|
---|
1896 | /// path. Any files within the named directory are added to the archive. Any
|
---|
1897 | /// subdirectories within the named directory are also added to the archive,
|
---|
1898 | /// recursively.
|
---|
1899 | /// </para>
|
---|
1900 | ///
|
---|
1901 | /// <para>
|
---|
1902 | /// Top-level entries in the named directory will appear as top-level entries
|
---|
1903 | /// in the zip archive. Entries in subdirectories in the named directory will
|
---|
1904 | /// result in entries in subdirectories in the zip archive.
|
---|
1905 | /// </para>
|
---|
1906 | ///
|
---|
1907 | /// <para>
|
---|
1908 | /// If you want the entries to appear in a containing directory in the zip
|
---|
1909 | /// archive itself, then you should call the AddDirectory() overload that
|
---|
1910 | /// allows you to explicitly specify a directory path for use in the archive.
|
---|
1911 | /// </para>
|
---|
1912 | ///
|
---|
1913 | /// <para>
|
---|
1914 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1915 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1916 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1917 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1918 | /// respective values at the time of this call will be applied to each
|
---|
1919 | /// ZipEntry added.
|
---|
1920 | /// </para>
|
---|
1921 | ///
|
---|
1922 | /// </remarks>
|
---|
1923 | ///
|
---|
1924 | /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string)"/>
|
---|
1925 | /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string)"/>
|
---|
1926 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string)"/>
|
---|
1927 | /// <seealso cref="Ionic.Zip.ZipFile.AddDirectory(string, string)"/>
|
---|
1928 | ///
|
---|
1929 | /// <overloads>This method has 2 overloads.</overloads>
|
---|
1930 | ///
|
---|
1931 | /// <param name="directoryName">The name of the directory to add.</param>
|
---|
1932 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
1933 | public ZipEntry AddDirectory(string directoryName)
|
---|
1934 | {
|
---|
1935 | return AddDirectory(directoryName, null);
|
---|
1936 | }
|
---|
1937 |
|
---|
1938 |
|
---|
1939 | /// <summary>
|
---|
1940 | /// Adds the contents of a filesystem directory to a Zip file archive,
|
---|
1941 | /// overriding the path to be used for entries in the archive.
|
---|
1942 | /// </summary>
|
---|
1943 | ///
|
---|
1944 | /// <remarks>
|
---|
1945 | /// <para>
|
---|
1946 | /// The name of the directory may be a relative path or a fully-qualified
|
---|
1947 | /// path. The add operation is recursive, so that any files or subdirectories
|
---|
1948 | /// within the name directory are also added to the archive.
|
---|
1949 | /// </para>
|
---|
1950 | ///
|
---|
1951 | /// <para>
|
---|
1952 | /// Top-level entries in the named directory will appear as top-level entries
|
---|
1953 | /// in the zip archive. Entries in subdirectories in the named directory will
|
---|
1954 | /// result in entries in subdirectories in the zip archive.
|
---|
1955 | /// </para>
|
---|
1956 | ///
|
---|
1957 | /// <para>
|
---|
1958 | /// For <c>ZipFile</c> properties including <see cref="Encryption"/>, <see
|
---|
1959 | /// cref="Password"/>, <see cref="SetCompression"/>, <see
|
---|
1960 | /// cref="ProvisionalAlternateEncoding"/>, <see cref="ExtractExistingFile"/>,
|
---|
1961 | /// <see cref="ZipErrorAction"/>, and <see cref="CompressionLevel"/>, their
|
---|
1962 | /// respective values at the time of this call will be applied to each
|
---|
1963 | /// ZipEntry added.
|
---|
1964 | /// </para>
|
---|
1965 | ///
|
---|
1966 | /// </remarks>
|
---|
1967 | ///
|
---|
1968 | /// <example>
|
---|
1969 | /// <para>
|
---|
1970 | /// In this code, calling the ZipUp() method with a value of "c:\reports" for
|
---|
1971 | /// the directory parameter will result in a zip file structure in which all
|
---|
1972 | /// entries are contained in a toplevel "reports" directory.
|
---|
1973 | /// </para>
|
---|
1974 | ///
|
---|
1975 | /// <code lang="C#">
|
---|
1976 | /// public void ZipUp(string targetZip, string directory)
|
---|
1977 | /// {
|
---|
1978 | /// using (var zip = new ZipFile())
|
---|
1979 | /// {
|
---|
1980 | /// zip.AddDirectory(directory, System.IO.Path.GetFileName(directory));
|
---|
1981 | /// zip.Save(targetZip);
|
---|
1982 | /// }
|
---|
1983 | /// }
|
---|
1984 | /// </code>
|
---|
1985 | /// </example>
|
---|
1986 | ///
|
---|
1987 | /// <seealso cref="Ionic.Zip.ZipFile.AddItem(string, string)"/>
|
---|
1988 | /// <seealso cref="Ionic.Zip.ZipFile.AddFile(string, string)"/>
|
---|
1989 | /// <seealso cref="Ionic.Zip.ZipFile.UpdateDirectory(string, string)"/>
|
---|
1990 | ///
|
---|
1991 | /// <param name="directoryName">The name of the directory to add.</param>
|
---|
1992 | ///
|
---|
1993 | /// <param name="directoryPathInArchive">
|
---|
1994 | /// Specifies a directory path to use to override any path in the
|
---|
1995 | /// DirectoryName. This path may, or may not, correspond to a real directory
|
---|
1996 | /// in the current filesystem. If the zip is later extracted, this is the
|
---|
1997 | /// path used for the extracted file or directory. Passing <c>null</c>
|
---|
1998 | /// (<c>Nothing</c> in VB) or the empty string ("") will insert the items at
|
---|
1999 | /// the root path within the archive.
|
---|
2000 | /// </param>
|
---|
2001 | ///
|
---|
2002 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
2003 | public ZipEntry AddDirectory(string directoryName, string directoryPathInArchive)
|
---|
2004 | {
|
---|
2005 | return AddOrUpdateDirectoryImpl(directoryName, directoryPathInArchive, AddOrUpdateAction.AddOnly);
|
---|
2006 | }
|
---|
2007 |
|
---|
2008 |
|
---|
2009 | /// <summary>
|
---|
2010 | /// Creates a directory in the zip archive.
|
---|
2011 | /// </summary>
|
---|
2012 | ///
|
---|
2013 | /// <remarks>
|
---|
2014 | ///
|
---|
2015 | /// <para>
|
---|
2016 | /// Use this when you want to create a directory in the archive but there is
|
---|
2017 | /// no corresponding filesystem representation for that directory.
|
---|
2018 | /// </para>
|
---|
2019 | ///
|
---|
2020 | /// <para>
|
---|
2021 | /// You will probably not need to do this in your code. One of the only times
|
---|
2022 | /// you will want to do this is if you want an empty directory in the zip
|
---|
2023 | /// archive. The reason: if you add a file to a zip archive that is stored
|
---|
2024 | /// within a multi-level directory, all of the directory tree is implicitly
|
---|
2025 | /// created in the zip archive.
|
---|
2026 | /// </para>
|
---|
2027 | ///
|
---|
2028 | /// </remarks>
|
---|
2029 | ///
|
---|
2030 | /// <param name="directoryNameInArchive">
|
---|
2031 | /// The name of the directory to create in the archive.
|
---|
2032 | /// </param>
|
---|
2033 | /// <returns>The <c>ZipEntry</c> added.</returns>
|
---|
2034 | public ZipEntry AddDirectoryByName(string directoryNameInArchive)
|
---|
2035 | {
|
---|
2036 | // workitem 9073
|
---|
2037 | ZipEntry dir = ZipEntry.CreateFromNothing(directoryNameInArchive);
|
---|
2038 | dir._container = new ZipContainer(this);
|
---|
2039 | dir.MarkAsDirectory();
|
---|
2040 | dir.AlternateEncoding = this.AlternateEncoding; // workitem 8984
|
---|
2041 | dir.AlternateEncodingUsage = this.AlternateEncodingUsage;
|
---|
2042 | dir.SetEntryTimes(DateTime.Now,DateTime.Now,DateTime.Now);
|
---|
2043 | dir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes;
|
---|
2044 | dir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes;
|
---|
2045 | dir._Source = ZipEntrySource.Stream;
|
---|
2046 | //string key = DictionaryKeyForEntry(dir);
|
---|
2047 | InternalAddEntry(dir.FileName,dir);
|
---|
2048 | AfterAddEntry(dir);
|
---|
2049 | return dir;
|
---|
2050 | }
|
---|
2051 |
|
---|
2052 |
|
---|
2053 |
|
---|
2054 | private ZipEntry AddOrUpdateDirectoryImpl(string directoryName,
|
---|
2055 | string rootDirectoryPathInArchive,
|
---|
2056 | AddOrUpdateAction action)
|
---|
2057 | {
|
---|
2058 | if (rootDirectoryPathInArchive == null)
|
---|
2059 | {
|
---|
2060 | rootDirectoryPathInArchive = "";
|
---|
2061 | }
|
---|
2062 |
|
---|
2063 | return AddOrUpdateDirectoryImpl(directoryName, rootDirectoryPathInArchive, action, true, 0);
|
---|
2064 | }
|
---|
2065 |
|
---|
2066 |
|
---|
2067 | internal void InternalAddEntry(String name, ZipEntry entry)
|
---|
2068 | {
|
---|
2069 | _entries.Add(name, entry);
|
---|
2070 | _zipEntriesAsList = null;
|
---|
2071 | _contentsChanged = true;
|
---|
2072 | }
|
---|
2073 |
|
---|
2074 |
|
---|
2075 |
|
---|
2076 | private ZipEntry AddOrUpdateDirectoryImpl(string directoryName,
|
---|
2077 | string rootDirectoryPathInArchive,
|
---|
2078 | AddOrUpdateAction action,
|
---|
2079 | bool recurse,
|
---|
2080 | int level)
|
---|
2081 | {
|
---|
2082 | if (Verbose)
|
---|
2083 | StatusMessageTextWriter.WriteLine("{0} {1}...",
|
---|
2084 | (action == AddOrUpdateAction.AddOnly) ? "adding" : "Adding or updating",
|
---|
2085 | directoryName);
|
---|
2086 |
|
---|
2087 | if (level == 0)
|
---|
2088 | {
|
---|
2089 | _addOperationCanceled = false;
|
---|
2090 | OnAddStarted();
|
---|
2091 | }
|
---|
2092 |
|
---|
2093 | // workitem 13371
|
---|
2094 | if (_addOperationCanceled)
|
---|
2095 | return null;
|
---|
2096 |
|
---|
2097 | string dirForEntries = rootDirectoryPathInArchive;
|
---|
2098 | ZipEntry baseDir = null;
|
---|
2099 |
|
---|
2100 | if (level > 0)
|
---|
2101 | {
|
---|
2102 | int f = directoryName.Length;
|
---|
2103 | for (int i = level; i > 0; i--)
|
---|
2104 | f = directoryName.LastIndexOfAny("/\\".ToCharArray(), f - 1, f - 1);
|
---|
2105 |
|
---|
2106 | dirForEntries = directoryName.Substring(f + 1);
|
---|
2107 | dirForEntries = Path.Combine(rootDirectoryPathInArchive, dirForEntries);
|
---|
2108 | }
|
---|
2109 |
|
---|
2110 | // if not top level, or if the root is non-empty, then explicitly add the directory
|
---|
2111 | if (level > 0 || rootDirectoryPathInArchive != "")
|
---|
2112 | {
|
---|
2113 | baseDir = ZipEntry.CreateFromFile(directoryName, dirForEntries);
|
---|
2114 | baseDir._container = new ZipContainer(this);
|
---|
2115 | baseDir.AlternateEncoding = this.AlternateEncoding; // workitem 6410
|
---|
2116 | baseDir.AlternateEncodingUsage = this.AlternateEncodingUsage;
|
---|
2117 | baseDir.MarkAsDirectory();
|
---|
2118 | baseDir.EmitTimesInWindowsFormatWhenSaving = _emitNtfsTimes;
|
---|
2119 | baseDir.EmitTimesInUnixFormatWhenSaving = _emitUnixTimes;
|
---|
2120 |
|
---|
2121 | // add the directory only if it does not exist.
|
---|
2122 | // It's not an error if it already exists.
|
---|
2123 | if (!_entries.ContainsKey(baseDir.FileName))
|
---|
2124 | {
|
---|
2125 | InternalAddEntry(baseDir.FileName,baseDir);
|
---|
2126 | AfterAddEntry(baseDir);
|
---|
2127 | }
|
---|
2128 | dirForEntries = baseDir.FileName;
|
---|
2129 | }
|
---|
2130 |
|
---|
2131 | if (!_addOperationCanceled)
|
---|
2132 | {
|
---|
2133 |
|
---|
2134 | String[] filenames = Directory.GetFiles(directoryName);
|
---|
2135 |
|
---|
2136 | if (recurse)
|
---|
2137 | {
|
---|
2138 | // add the files:
|
---|
2139 | foreach (String filename in filenames)
|
---|
2140 | {
|
---|
2141 | if (_addOperationCanceled) break;
|
---|
2142 | if (action == AddOrUpdateAction.AddOnly)
|
---|
2143 | AddFile(filename, dirForEntries);
|
---|
2144 | else
|
---|
2145 | UpdateFile(filename, dirForEntries);
|
---|
2146 | }
|
---|
2147 |
|
---|
2148 | if (!_addOperationCanceled)
|
---|
2149 | {
|
---|
2150 | // add the subdirectories:
|
---|
2151 | String[] dirnames = Directory.GetDirectories(directoryName);
|
---|
2152 | foreach (String dir in dirnames)
|
---|
2153 | {
|
---|
2154 | // workitem 8617: Optionally traverse reparse points
|
---|
2155 | #if SILVERLIGHT
|
---|
2156 | #elif NETCF
|
---|
2157 | FileAttributes fileAttrs = (FileAttributes) NetCfFile.GetAttributes(dir);
|
---|
2158 | #else
|
---|
2159 | FileAttributes fileAttrs = System.IO.File.GetAttributes(dir);
|
---|
2160 | #endif
|
---|
2161 | if (this.AddDirectoryWillTraverseReparsePoints
|
---|
2162 | #if !SILVERLIGHT
|
---|
2163 | || ((fileAttrs & FileAttributes.ReparsePoint) == 0)
|
---|
2164 | #endif
|
---|
2165 | )
|
---|
2166 | AddOrUpdateDirectoryImpl(dir, rootDirectoryPathInArchive, action, recurse, level + 1);
|
---|
2167 |
|
---|
2168 | }
|
---|
2169 |
|
---|
2170 | }
|
---|
2171 | }
|
---|
2172 | }
|
---|
2173 |
|
---|
2174 | if (level == 0)
|
---|
2175 | OnAddCompleted();
|
---|
2176 |
|
---|
2177 | return baseDir;
|
---|
2178 | }
|
---|
2179 |
|
---|
2180 | }
|
---|
2181 |
|
---|
2182 | }
|
---|