/// <summary>Asynchronously deletes all the <b>ZipArchiveEntries</b> specified from the zip file.</summary> public async Task DeleteFromZipArchiveAsync(IEnumerable <string> paths, string zipFileName) { using (var memoryStream = new MemoryStream(await FileAsync.ReadAllBytesAsync(zipFileName))) { using (var zip = new ZipArchive(memoryStream, ZipArchiveMode.Update)) { foreach (var entry in zip.Entries.Where(e => paths.Contains(e.FullName)).ToArray()) { if (entry != null) { try { entry.Delete(); } catch (Exception ex) { string entryDescription = entry.FullName.IndexOfAny(XBRLConstants.DelimiterChars) == -1 ? entry.FullName : entry.FullName.Substring(entry.FullName.LastIndexOfAny(XBRLConstants.DelimiterChars) + 1); OnError(new ZipErrorEventArgs( string.Format("Error deleting '{0}' from '{1}'. {2}.", entryDescription, Path.GetFileName(zipFileName), ex.Message))); } } } } await FileAsync.WriteAllBytesAsync(zipFileName, memoryStream.ToArray()); } }
/// <summary>Save a file (or files) to zip asynchronously, using asynchronous IO.</summary> /// <param name="paths">The files and/or directories to create a zip file.</param> /// <param name="zipFileName">The path of the zip file to create.</param> /// <param name="filesToExclude">(Optional) Any file names that should be excluded.</param> /// <returns>A Task that represents completion of the method.</returns> public async Task CreateZipArchiveAsync(IEnumerable <string> paths, string zipFileName, params string[] filesToExclude) { var files = await BuildFileCollectionAsync(paths, filesToExclude); using (var stream = new FileStream(zipFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.None, XBRLConstants.LargeBufferSize, true)) { // ZipArchiveMode.Update mode is required here to allow setting entries' last write time, after creating and writing them. using (var zip = new ZipArchive(stream, ZipArchiveMode.Update)) { var count = 0; var total = files.Count(); foreach (var kvp in files) { try { using (var memoryStream = new MemoryStream(await FileAsync.ReadAllBytesAsync(kvp.Key))) { if (memoryStream.Length > 0) { ZipArchiveEntry entry; using (var zipStream = (entry = zip.CreateEntry(kvp.Value, CompressionLevel.Optimal)).Open()) { await memoryStream.CopyToAsync(zipStream, XBRLConstants.LargeBufferSize); } var fileInfo = new FileInfo(kvp.Key); entry.LastWriteTime = new DateTimeOffset(fileInfo.LastWriteTime); OnProgress(new ZipProgressEventArgs(kvp.Key, kvp.Value, ++count, total, ZipAction.Add)); } else { total--; } } } catch (Exception ex) { OnError(new ZipErrorEventArgs(string.Format("Error adding '{0}'. {1}.", Path.GetFileName(kvp.Key), ex.Message))); } } } } }
/// <summary>Add a file (or files) to a zip asynchronously, using asynchronous IO.</summary> /// <remarks>This is exactly the same as the <see cref="CreateZipArchiveAsync"/> method, /// except that it updates an existing zip file.</remarks> /// <param name="paths">The files and/or directories to add to a zip file.</param> /// <param name="zipFileName">The path of the zip file to update.</param> /// <param name="filesToExclude">(Optional) Any file names that should be excluded.</param> /// <returns>A Task that represents completion of the method.</returns> public async Task UpdateZipArchiveAsync(IEnumerable <string> paths, string zipFileName, params string[] filesToExclude) { var files = await BuildFileCollectionAsync(paths, filesToExclude); /* Note the FileShare parameter needs to be FileShare.Read here. Otherwise, if the zip file * is already open in another process, the FileStream constructor will throw an exception. */ using (var stream = new FileStream(zipFileName, FileMode.Open, FileAccess.ReadWrite, FileShare.Read, XBRLConstants.LargeBufferSize, true)) { using (var zip = new ZipArchive(stream, ZipArchiveMode.Update)) { var count = 0; foreach (var kvp in files) { try { using (var memoryStream = new MemoryStream(await FileAsync.ReadAllBytesAsync(kvp.Key))) { if (memoryStream.Length > 0) { ZipArchiveEntry entry; using (var zipStream = (entry = zip.CreateOrOpenEntry(kvp.Value)).Open()) { await memoryStream.CopyToAsync(zipStream, XBRLConstants.LargeBufferSize); } var fileInfo = new FileInfo(kvp.Key); entry.LastWriteTime = new DateTimeOffset(fileInfo.LastWriteTime); OnProgress(new ZipProgressEventArgs(kvp.Key, kvp.Value, ++count, files.Count(), ZipAction.Add)); } } } catch (Exception ex) { OnError(new ZipErrorEventArgs(string.Format("Error updating '{0}' with '{1}'. {2}.", Path.GetFileName(zipFileName), Path.GetFileName(kvp.Key), ex.Message))); } } } } }