@page "/serilogs/file" @using System.IO @using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Hosting @using Microsoft.JSInterop @using MudBlazor @using System.Linq @inject IWebHostEnvironment Env @inject IJSRuntime JS @inject IConfiguration Configuration @inject ISnackbar Snackbar
File Logs Browse and download log files stored on the local server storage.
/ Serilogs / File
Search
@if (_isRefreshing) { Refreshing... } else { Refresh } @if (_selectedFile != null) { @if (_isDownloading) { Downloading... } else { Download File } }
File Name Last Modified Size
@context.FileName
@context.LastModified.ToString("yyyy-MM-dd HH:mm:ss") @context.FileSize
Rows per page: Showing @(GetFilteredData().Count() == 0 ? 0 : _skip + 1) - @Math.Min(_skip + _top, GetFilteredData().Count()) of @GetFilteredData().Count()
Prev @{ var totalPages = _totalPage == 0 ? 1 : _totalPage; var maxVisible = 5; var startPage = Math.Max(1, _currentPage - maxVisible / 2); var endPage = Math.Min(totalPages, startPage + maxVisible - 1); if (endPage - startPage < maxVisible - 1) { startPage = Math.Max(1, endPage - maxVisible + 1); } } @for (int i = startPage; i <= endPage; i++) { var pageNum = i; var isActive = pageNum == _currentPage; @pageNum } Next
@code { private List _allLogFiles = new(); private LogFileInfo? _selectedFile; private string _searchString = ""; private bool _isRefreshing = false; private bool _isDownloading = false; private int _skip = 0; private int _top = 5; private int _totalPage => GetFilteredData().Count() == 0 ? 0 : (int)Math.Ceiling((double)GetFilteredData().Count() / _top); private int _currentPage => (_skip / _top) + 1; public class LogFileInfo { public string FileName { get; set; } = ""; public string FullPath { get; set; } = ""; public DateTime LastModified { get; set; } public string FileSize { get; set; } = ""; public long SizeInBytes { get; set; } } protected override void OnInitialized() { LoadFiles(); } private async Task HandleRefresh() { _isRefreshing = true; _selectedFile = null; _skip = 0; StateHasChanged(); await Task.Delay(800); LoadFiles(); _isRefreshing = false; StateHasChanged(); } private void LoadFiles() { _allLogFiles.Clear(); string configPath = Configuration["LoggerSettings:File:Path"] ?? "wwwroot/xlogs/app-log-.txt"; string? directoryPath = Path.GetDirectoryName(configPath); if (string.IsNullOrEmpty(directoryPath)) directoryPath = "wwwroot/xlogs"; string fullDirectoryPath = Path.Combine(Env.ContentRootPath, directoryPath); if (Directory.Exists(fullDirectoryPath)) { var files = new DirectoryInfo(fullDirectoryPath).GetFiles("*.txt"); foreach (var file in files.OrderByDescending(f => f.LastWriteTime)) { _allLogFiles.Add(new LogFileInfo { FileName = file.Name, FullPath = file.FullName, LastModified = file.LastWriteTime, SizeInBytes = file.Length, FileSize = GetFriendlyFileSize(file.Length) }); } } } private IEnumerable GetFilteredData() { if (string.IsNullOrWhiteSpace(_searchString)) return _allLogFiles; return _allLogFiles.Where(x => x.FileName.Contains(_searchString, StringComparison.OrdinalIgnoreCase)); } private IEnumerable GetPagedData() => GetFilteredData().Skip(_skip).Take(_top); private void OnSearchClick() { _skip = 0; _selectedFile = null; StateHasChanged(); } private void HandleSearchKeyDown(KeyboardEventArgs e) { if (e.Key == "Enter") OnSearchClick(); } private void OnPageChanged(int page) { if (page >= 1 && page <= _totalPage) { _skip = (page - 1) * _top; _selectedFile = null; StateHasChanged(); } } private void OnPageSizeChanged(int size) { _top = size; _skip = 0; _selectedFile = null; StateHasChanged(); } private void HandleRowClick(TableRowClickEventArgs args) { _selectedFile = (_selectedFile?.FullPath == args.Item.FullPath) ? null : args.Item; } private async Task DownloadFile() { if (_selectedFile == null) return; _isDownloading = true; StateHasChanged(); try { await Task.Delay(1000); var bytes = await File.ReadAllBytesAsync(_selectedFile.FullPath); using var stream = new MemoryStream(bytes); using var streamRef = new DotNetStreamReference(stream); await JS.InvokeVoidAsync("downloadFileFromStream", _selectedFile.FileName, streamRef); Snackbar.Add("Log file downloaded successfully", Severity.Success); } catch (Exception ex) { Snackbar.Add($"Download failed: {ex.Message}", Severity.Error); } finally { _isDownloading = false; StateHasChanged(); } } private string GetFriendlyFileSize(long bytes) { string[] suffix = { "B", "KB", "MB", "GB" }; int i; double dblSByte = bytes; for (i = 0; i < suffix.Length && bytes >= 1024; i++, bytes /= 1024) { dblSByte = bytes / 1024.0; } return $"{dblSByte:0.##} {suffix[i]}"; } }