在.NetCore里操作物理文件,其实是比较常见的动作。
我们今天来梳理下几个操作,包括(1)依赖注入文件系统,(2)读取文件内容,(3)文件改变时触发事件;
一、依赖注入
在ConfigureServices里我们将操作物理文件的方法进行依赖注入;
IFileProvider physicalProvider = new PhysicalFileProvider(@"D:\Test\WebAPITest"); services.AddSingleton<IFileProvider>(physicalProvider);
注意,这里必须使用Signleton单例模式的依赖注入。New一个物理文件提供方法PhysicalFileProvider,并且指定根目录地址。
思考:若是有多个根目录,依赖注入其实并非完美的解决方案,因为这里只能指定一个目录,解决办法有两种,第一种使用AutoFac指定key或者Name;第二种直接放弃依赖注入,采用New全新创建的方法;接下来我们使用第2种方法进行操作。
二、读取文件内容
首先我们要创建一个控制器,写一个读取文件的方法。
private async Task<string> ReadAsync(string path) { PhysicalFileProvider _fileProvider= new PhysicalFileProvider(@"D:\Test\WebAPITest"); await using var stream = _fileProvider.GetFileInfo(path).CreateReadStream(); var buffer = new byte[stream.Length]; await stream.ReadAsync(buffer, 0, buffer.Length); return Encoding.Default.GetString(buffer); }
递归读取文件目录和文件名的方法如下:
/// <summary>
/// 读取文件目录和文件名
/// </summary>
public void Dir()
{
var indent = -1;
void Get(string subpath)
{
indent++;
foreach (var fileinfo in _fileProvider.GetDirectoryContents(subpath))
{
Console.WriteLine(new string('\t', indent) + fileinfo.Name);
if (fileinfo.IsDirectory)
{
Get($@"{subpath}\{fileinfo.Name}");
}
}
}
Get("");
}
三、文件变化的时候触发事件:
using Microsoft.Extensions.Primitives;
[HttpGet]
public async Task<string> Get()
{
_fileProvider = new PhysicalFileProvider(@"D:\Test\WebAPITest");
string path= @"111.txt";
Console.WriteLine(await ReadAsync(path));
ChangeToken.OnChange(() => _fileProvider.Watch(path), async () =>
{
// 这里写你的逻辑
Console.WriteLine("文件变化了");
Console.WriteLine(await ReadAsync(path));
});
return "ok";
}
该类的全部源码如下:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Primitives;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace WebAPITest.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class FileTestController : ControllerBase
{
PhysicalFileProvider _fileProvider;
public FileTestController( )
{
}
// GET: api/<FileTestController>
[HttpGet]
public async Task<string> Get()
{
_fileProvider = new PhysicalFileProvider(@"D:\Test\WebAPITest");
string path= @"111.txt";
Console.WriteLine(await ReadAsync(path));
ChangeToken.OnChange(() => _fileProvider.Watch(path), async () =>
{
// 这里写你的逻辑
Console.WriteLine("文件变化了");
Console.Clear();
Console.WriteLine(await ReadAsync(path));
});
return "ok";
}
/// <summary>
/// 读取文件目录和文件名
/// </summary>
public void Dir()
{
var indent = -1;
void Get(string subpath)
{
indent++;
foreach (var fileinfo in _fileProvider.GetDirectoryContents(subpath))
{
Console.WriteLine(new string('\t', indent) + fileinfo.Name);
if (fileinfo.IsDirectory)
{
Get($@"{subpath}\{fileinfo.Name}");
}
}
}
Get("");
}
private async Task<string> ReadAsync(string path)
{
await using var stream = _fileProvider.GetFileInfo(path).CreateReadStream();
var buffer = new byte[stream.Length];
await stream.ReadAsync(buffer, 0, buffer.Length);
return Encoding.Default.GetString(buffer);
}
}
}