using EmbedIO.Utilities;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Threading;
namespace EmbedIO.Files
{
///
/// Provides access to files contained in a .zip file to a .
///
///
public class ZipFileProvider : IDisposable, IFileProvider
{
private readonly ZipArchive _zipArchive;
///
/// Initializes a new instance of the class.
///
/// The zip file path.
public ZipFileProvider(string zipFilePath)
: this(new FileStream(Validate.LocalPath(nameof(zipFilePath), zipFilePath, true), FileMode.Open))
{
}
///
/// Initializes a new instance of the class.
///
/// The stream that contains the archive.
/// to leave the stream open after the web server
/// is disposed; otherwise, .
public ZipFileProvider(Stream stream, bool leaveOpen = false)
{
_zipArchive = new ZipArchive(stream, ZipArchiveMode.Read, leaveOpen);
}
///
/// Finalizes an instance of the class.
///
~ZipFileProvider()
{
Dispose(false);
}
///
public event Action ResourceChanged
{
add { }
remove { }
}
///
public bool IsImmutable => true;
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
public void Start(CancellationToken cancellationToken)
{
}
///
public MappedResourceInfo? MapUrlPath(string urlPath, IMimeTypeProvider mimeTypeProvider)
{
if (urlPath.Length == 1)
return null;
urlPath = Uri.UnescapeDataString(urlPath);
var entry = _zipArchive.GetEntry(urlPath.Substring(1));
if (entry == null)
return null;
return MappedResourceInfo.ForFile(
entry.FullName,
entry.Name,
entry.LastWriteTime.DateTime,
entry.Length,
mimeTypeProvider.GetMimeType(Path.GetExtension(entry.Name)));
}
///
public Stream OpenFile(string path)
=> _zipArchive.GetEntry(path)?.Open() ?? throw new FileNotFoundException($"\"{path}\" cannot be found in Zip archive.");
///
public IEnumerable GetDirectoryEntries(string path, IMimeTypeProvider mimeTypeProvider)
=> Enumerable.Empty();
///
/// Releases unmanaged and - optionally - managed resources.
///
/// to release both managed and unmanaged resources;
/// to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (!disposing)
return;
_zipArchive.Dispose();
}
}
}