File: System\IO\Compression\ZipFileExtensions.ZipArchiveEntry.Extract.Async.cs
Web Access
Project: src\src\libraries\System.IO.Compression.ZipFile\src\System.IO.Compression.ZipFile.csproj (System.IO.Compression.ZipFile)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Threading;
using System.Threading.Tasks;
 
namespace System.IO.Compression;
 
public static partial class ZipFileExtensions
{
    /// <summary>
    /// Asynchronously creates a file on the file system with the entry's contents and the specified name. The last write time of the file is set to the
    /// entry's last write time. This method does not allow overwriting of an existing file with the same name. Attempting to extract explicit
    /// directories (entries with names that end in directory separator characters) will not result in the creation of a directory.
    /// </summary>
    ///
    /// <exception cref="UnauthorizedAccessException">The caller does not have the required permission.</exception>
    /// <exception cref="ArgumentException">destinationFileName is a zero-length string, contains only whitespace, or contains one or more
    /// invalid characters as defined by InvalidPathChars. -or- destinationFileName specifies a directory.</exception>
    /// <exception cref="ArgumentNullException">destinationFileName is null.</exception>
    /// <exception cref="PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length.
    /// For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.</exception>
    /// <exception cref="DirectoryNotFoundException">The path specified in destinationFileName is invalid (for example, it is on
    /// an unmapped drive).</exception>
    /// <exception cref="IOException">An I/O error has occurred. -or- The entry is currently open for writing.
    /// -or- The entry has been deleted from the archive.</exception>
    /// <exception cref="NotSupportedException">destinationFileName is in an invalid format
    /// -or- The ZipArchive that this entry belongs to was opened in a write-only mode.</exception>
    /// <exception cref="InvalidDataException">The entry is missing from the archive or is corrupt and cannot be read
    /// -or- The entry has been compressed using a compression method that is not supported.</exception>
    /// <exception cref="ObjectDisposedException">The ZipArchive that this entry belongs to has been disposed.</exception>
    /// <param name="source">The zip archive entry to extract a file from.</param>
    /// <param name="destinationFileName">The name of the file that will hold the contents of the entry.
    /// The path is permitted to specify relative or absolute path information.
    /// Relative path information is interpreted as relative to the current working directory.</param>
    /// /// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
    public static Task ExtractToFileAsync(this ZipArchiveEntry source, string destinationFileName, CancellationToken cancellationToken = default) =>
        ExtractToFileAsync(source, destinationFileName, false, cancellationToken);
 
    /// <summary>
    /// Asynchronously creates a file on the file system with the entry's contents and the specified name.
    /// The last write time of the file is set to the entry's last write time.
    /// This method does allows overwriting of an existing file with the same name.
    /// </summary>
    /// <exception cref="UnauthorizedAccessException">The caller does not have the required permission.</exception>
    /// <exception cref="ArgumentException">destinationFileName is a zero-length string, contains only whitespace,
    /// or contains one or more invalid characters as defined by InvalidPathChars. -or- destinationFileName specifies a directory.</exception>
    /// <exception cref="ArgumentNullException">destinationFileName is null.</exception>
    /// <exception cref="PathTooLongException">The specified path, file name, or both exceed the system-defined maximum length.
    /// For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.</exception>
    /// <exception cref="DirectoryNotFoundException">The path specified in destinationFileName is invalid
    /// (for example, it is on an unmapped drive).</exception>
    /// <exception cref="IOException">An I/O error has occurred.
    /// -or- The entry is currently open for writing.
    /// -or- The entry has been deleted from the archive.</exception>
    /// <exception cref="NotSupportedException">destinationFileName is in an invalid format
    /// -or- The ZipArchive that this entry belongs to was opened in a write-only mode.</exception>
    /// <exception cref="InvalidDataException">The entry is missing from the archive or is corrupt and cannot be read
    /// -or- The entry has been compressed using a compression method that is not supported.</exception>
    /// <exception cref="ObjectDisposedException">The ZipArchive that this entry belongs to has been disposed.</exception>
    /// <exception cref="OperationCanceledException">An asynchronous operation is cancelled.</exception>
    /// <param name="source">The zip archive entry to extract a file from.</param>
    /// <param name="destinationFileName">The name of the file that will hold the contents of the entry.
    /// The path is permitted to specify relative or absolute path information.
    /// Relative path information is interpreted as relative to the current working directory.</param>
    /// <param name="overwrite">True to indicate overwrite.</param>
    /// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
    public static async Task ExtractToFileAsync(this ZipArchiveEntry source, string destinationFileName, bool overwrite, CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();
 
        ExtractToFileInitialize(source, destinationFileName, overwrite, out FileStreamOptions fileStreamOptions);
 
        FileStream fs = new FileStream(destinationFileName, fileStreamOptions);
        await using (fs)
        {
            Stream es = await source.OpenAsync(cancellationToken).ConfigureAwait(false);
            await using (es)
            {
                await es.CopyToAsync(fs, cancellationToken).ConfigureAwait(false);
            }
        }
 
        ExtractToFileFinalize(source, destinationFileName);
    }
 
    internal static async Task ExtractRelativeToDirectoryAsync(this ZipArchiveEntry source, string destinationDirectoryName, bool overwrite, CancellationToken cancellationToken = default)
    {
        cancellationToken.ThrowIfCancellationRequested();
 
        if (ExtractRelativeToDirectoryCheckIfFile(source, destinationDirectoryName, out string fileDestinationPath))
        {
            // If it is a file:
            // Create containing directory:
            Directory.CreateDirectory(Path.GetDirectoryName(fileDestinationPath)!);
            await source.ExtractToFileAsync(fileDestinationPath, overwrite: overwrite, cancellationToken).ConfigureAwait(false);
        }
    }
}