最近在用abpvnext做报表导出,涉及到要在站点根目录生成pdf文件提供下载。于是就要获取站点根路径。
开头搜索资料提示用IWebHostEnvironment.ContentRootPath,来实现获取站点根目录。这个其实是正解。.netcore的通用规则,使用任何借口都是依赖注入,我是觉得这玩意挺麻烦的。
但是我是在一个业务类里面实现pdf文件生成,为了保持这个业务类的相对独立性,我又偷懒不想将IWebHostEnvironment通过控制器逐层传递依赖注入到业务类里面。
鬼使神差的不知道怎么的搜到了可以使用AppContext.BaseDirectory
属性来获取当前应用程序的根目录。重点是他不用注入再逐层传递啊, 不管三七二十一就用上了。 然后文件也能正常的在项目的bin\wwwroot 目录下面生成文件,但是等我用http+相对文件路径去到浏览器里访问文件的时候,他就死都访问不到,路径举例:
http://localhost:44315/File/Report/20231130/温湿度曲线报表_20231130000000130.pdf
然后调试了很久,各种办法试,发现http方式只能访问到项目的根目录JQ.TAHM.HttpApi.Host这一级,在这一级的wwwroot目录里的文件是可以访问到的。 但是往下的 bin\Debug\net6.0\wwwroot\File\Report\20231130 这种,http他是访问不到的。
那就只能改为用IHostEnvironment,或者IWebHostEnvironment 来获取站点根目录了。使用IHostEnvironment.ContentRootPath 他这个获取到的是bin的父级 (站点根目录JQ.TAHM.HttpApi.Host)
正好我还有了不用逐层注入传递接口,直接使用IHostEnvironment的办法。
下面这一行代码就可以通过IHostEnvironment取到站点根路径下的wwwroot。
var parentPath = Path.Combine(IOCProvider.GetService<IHostEnvironment>().ContentRootPath,"wwwroot");
如下图
重点在IOCProvider.GetService<IHostEnvironment>() 这个东西 的IOCProvider类代码如下,文件放在application层跟service平级的 。
我浅显的个人猜测,这个类的ServiceProvider.GetService原理应该是通过反射从容器获取到传递进来的任何接口(类型)的实例。拿到实例了想干嘛就干嘛了,这样省去了一直需要通过注入来使用接口和接口的属性和方法的麻烦。
public static class IOCProvider
{
public static IServiceProvider ServiceProvider { get; set; }
/// <summary>
///
/// </summary>
public static T GetService<T> ()=> (T)IOCProvider.ServiceProvider.GetService(typeof(T));
}
他这个可以一次性引入,还涉及另外两个地方
Program 的main当中使用 UseIOC()
CreateHostBuilder(args).Build().UseIOC().Run(); //这句应该是调用接下来的IOCExtensions.UseIOC 给上面的IOCProvider类初始化。
IOCExtensions类的UseIOC方法
public static class IOCExtensions
{
public static IHost UseIOC(this IHost host)
{
IOCProvider.ServiceProvider = host.Services;
return host;
}
}