diff --git a/Oqtane.Client/Modules/Admin/Files/Details.razor b/Oqtane.Client/Modules/Admin/Files/Details.razor index 56eca8c7..2b707af5 100644 --- a/Oqtane.Client/Modules/Admin/Files/Details.razor +++ b/Oqtane.Client/Modules/Admin/Files/Details.razor @@ -40,10 +40,14 @@ +
@SharedLocalizer["Cancel"] -
-
+ @if (_name.ToLower().EndsWith(".zip")) + { + + } +

} @@ -126,4 +130,18 @@ AddModuleMessage(SharedLocalizer["Message.InfoRequired"], MessageType.Warning); } } + + private async Task UnzipFile() + { + try + { + await FileService.UnzipFileAsync(_fileId); + NavigationManager.NavigateTo(NavigateUrl()); + } + catch (Exception ex) + { + await logger.LogError(ex, "Error Unzipping File {FileId} {Error}", _fileId, ex.Message); + AddModuleMessage(Localizer["Error.File.Unzip"], MessageType.Error); + } + } } \ No newline at end of file diff --git a/Oqtane.Client/Services/FileService.cs b/Oqtane.Client/Services/FileService.cs index 05d3adff..9bc563c6 100644 --- a/Oqtane.Client/Services/FileService.cs +++ b/Oqtane.Client/Services/FileService.cs @@ -75,5 +75,10 @@ namespace Oqtane.Services { return await GetByteArrayAsync($"{Apiurl}/download/{fileId}"); } + + public async Task UnzipFileAsync(int fileId) + { + await PutAsync($"{Apiurl}/unzip/{fileId}"); + } } } diff --git a/Oqtane.Client/Services/Interfaces/IFileService.cs b/Oqtane.Client/Services/Interfaces/IFileService.cs index 1174947f..451d3c4d 100644 --- a/Oqtane.Client/Services/Interfaces/IFileService.cs +++ b/Oqtane.Client/Services/Interfaces/IFileService.cs @@ -92,5 +92,13 @@ namespace Oqtane.Services /// /// Task> GetFilesAsync(int siteId, string folderPath); + + /// + /// Unzips the contents of a zip file + /// + /// Reference to the + /// + /// + Task UnzipFileAsync(int fileId); } } diff --git a/Oqtane.Client/Services/SettingService.cs b/Oqtane.Client/Services/SettingService.cs index 5176da7a..4a43972e 100644 --- a/Oqtane.Client/Services/SettingService.cs +++ b/Oqtane.Client/Services/SettingService.cs @@ -194,7 +194,7 @@ namespace Oqtane.Services public async Task AddOrUpdateSettingAsync(string entityName, int entityId, string settingName, string settingValue, bool isPrivate) { - await PutJsonAsync($"{Apiurl}/{entityName}/{entityId}/{settingName}/{settingValue}/{isPrivate}", null); + await PutAsync($"{Apiurl}/{entityName}/{entityId}/{settingName}/{settingValue}/{isPrivate}"); } public async Task DeleteSettingAsync(string entityName, int entityId, string settingName) diff --git a/Oqtane.Server/Controllers/FileController.cs b/Oqtane.Server/Controllers/FileController.cs index b82b133e..030005f5 100644 --- a/Oqtane.Server/Controllers/FileController.cs +++ b/Oqtane.Server/Controllers/FileController.cs @@ -21,6 +21,7 @@ using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Formats.Png; using System.Net.Http; using Microsoft.AspNetCore.Cors; +using System.IO.Compression; // ReSharper disable StringIndexOfIsCultureSpecific.1 @@ -177,9 +178,12 @@ namespace Oqtane.Controllers if (System.IO.File.Exists(filepath)) { file = CreateFile(file.Name, folder.FolderId, filepath); - file = _files.AddFile(file); - _syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, SyncEventActions.Create); - _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Added {File}", file); + if (file != null) + { + file = _files.AddFile(file); + _syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, SyncEventActions.Create); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Added {File}", file); + } } else { @@ -265,6 +269,57 @@ namespace Oqtane.Controllers return file; } + // PUT api//unzip/5 + [HttpPut("unzip/{id}")] + [Authorize(Roles = RoleNames.Admin)] + public void Unzip(int id) + { + var zipfile = _files.GetFile(id, false); + if (zipfile != null && zipfile.Folder.SiteId == _alias.SiteId && zipfile.Extension.ToLower() == "zip") + { + // extract files + string folderpath = _folders.GetFolderPath(zipfile.Folder); + using (ZipArchive archive = ZipFile.OpenRead(Path.Combine(folderpath, zipfile.Name))) + { + foreach (ZipArchiveEntry entry in archive.Entries) + { + if (HasValidFileExtension(entry.Name) && entry.Name.IsPathOrFileValid()) + { + entry.ExtractToFile(Path.Combine(folderpath, entry.Name), true); + var file = CreateFile(entry.Name, zipfile.Folder.FolderId, Path.Combine(folderpath, entry.Name)); + if (file != null) + { + if (file.FileId == 0) + { + file = _files.AddFile(file); + } + else + { + file = _files.UpdateFile(file); + } + _syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, SyncEventActions.Create); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Extracted {File}", file); + } + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "File Name Is Invalid Or Contains Invalid Extension {File}", entry.Name); + } + } + } + + // delete zip file + _files.DeleteFile(zipfile.FileId); + System.IO.File.Delete(Path.Combine(folderpath, zipfile.Name)); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "Zip File Removed {File}", zipfile); + } + else + { + _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized File Unzip Attempt {FileId}", id); + HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden; + } + } + // DELETE api//5 [HttpDelete("{id}")] [Authorize(Roles = RoleNames.Registered)] @@ -342,6 +397,7 @@ namespace Oqtane.Controllers if (file != null) { file = _files.AddFile(file); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Downloaded {File}", file); _syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, SyncEventActions.Create); } } @@ -426,7 +482,7 @@ namespace Oqtane.Controllers { file = _files.UpdateFile(file); } - _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Upload Succeeded {File}", Path.Combine(folderPath, upload)); + _logger.Log(LogLevel.Information, this, LogFunction.Create, "File Uploaded {File}", Path.Combine(folderPath, upload)); _syncManager.AddSyncEvent(_alias, EntityNames.File, file.FileId, SyncEventActions.Create); } } @@ -836,6 +892,7 @@ namespace Oqtane.Controllers { _files.DeleteFile(file.FileId); } + file = null; _logger.Log(LogLevel.Warning, this, LogFunction.Create, "File Exceeds Folder Capacity And Has Been Removed {Folder} {File}", folder, filepath); }