如何下载从 log4Net 生成的日志文件

How to Download log files generated from log4Net

我在 ASP.NET MVC 4 应用程序中使用 log4net,我正在尝试从 log4Net 下载生成的日志文件。

我想下载带有 FileResult 的日志文件,例如:

[Authorize(Roles = "Admin")]
public FileResult DownloadUserInterfaceLog()
{
    // Get the path of the log file
    string path = (LogManager.GetCurrentLoggers()[0].Logger.Repository.GetAppenders()[0] as FileAppender).File;
    // Get the file
    byte[] fileBytes = System.IO.File.ReadAllBytes(path);
    string fileName = "Log.txt";
    // Return the expected file
    return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName);
}

我的问题是,当我调用 System.IO.File.ReadAllBytes(path); 时出现异常,导致日志文件已被另一个进程使用。

我已经输入 <lockingModel value="log4net.Appender.FileAppender+MinimalLock" /> (which should release the file after any modification) in my Web.Config 但没有成功。

Web.Config 中的 log4Net 配置开始:

<log4net>
    <appender name="Appender-root" type="log4net.Appender.RollingFileAppender">
        <lockingModel value="log4net.Appender.FileAppender+MinimalLock" />
        <file value="Path..." />
        <appendToFile value="true" />

您需要在访问文件之前关闭 Appender:

((FileAppender)LogManager.GetCurrentLoggers()[0].Logger.Repository.GetAppenders()[0]).Close()

Here 是一篇关于类似问题的文章。

File.ReadAllBytes() function is written such that it uses a call like the following to instantiate a FileStream:

FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)

Notice that the FileShare is specified as Read. That means if you have another piece of code writing to the same file at the same time, you will get an error even if the other piece of code created the FileStream by specifying the share mode as “ReadWrite” like so:

FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite)

解决方案是编写您自己的自定义 ReadAllBytes:

public static byte[] ReadAllBytes(String path)
{
    byte[] bytes;
    using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
    {
        int index = 0;
        long fileLength = fs.Length;
        if (fileLength > Int32.MaxValue)
            throw new IOException(“File too long”);
        int count = (int)fileLength;
        bytes = new byte[count];
        while (count > 0)
        {
            int n = fs.Read(bytes, index, count);
            if (n == 0)
                throw new InvalidOperationException(“End of file reached before expected”);
            index += n;
            count -= n;
        }
    }
return bytes;
}

这对我有用

            var logFile = System.Web.HttpContext.Current.Server.MapPath("/Log.txt");
            if (System.IO.File.Exists(logFile))
            {
                var copyFile = logFile.Replace(".txt", "");
                System.IO.File.Copy(logFile, copyFile);
                var bytes = System.IO.File.ReadAllBytes(copyFile);
                System.IO.File.Delete(copyFile);
                return bytes;

            }

但是,下面的代码可以用来打开文件而不抛出异常

using (var stream = File.Open(selectedItem.FileFullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                using (var streamReader = new StreamReader(stream))
                {
                    while (streamReader.Peek() > -1)
                    {
                        var line = streamReader.ReadLine();
                        // . . .
                    }
                }
            }