虚拟文件结果文件存在时找不到文件

本文关键字:文件 找不到 结果 虚拟 存在 | 更新日期: 2023-09-27 18:36:28

也许我不明白VirtualFileResult是什么,但我不确定为什么当文件存在时它会抛出FileNotFoundException。代码如下:

if (System.IO.File.Exists(fileName))
{
    FileInfo info = new FileInfo(fileName);
    return File(fileName, FileUtility.GetContentType(fileName), info.Name);
}

(编辑:FileUtility.GetContentType(正确)返回文件的 Mime 类型,在我的情况下是 "application/pdf"

这是我得到的例外:(我删除了文件路径)

System.IO.FileNotFoundException: Could not find file: [file path removed]
File name: '[file path removed]'
   at Microsoft.AspNet.Mvc.VirtualFileResult.<WriteFileAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeResultAsync>d__56.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeResultFilterAsync>d__55.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeAllResultFiltersAsync>d__54.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeResourceFilterAsync>d__49.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at Microsoft.AspNet.Mvc.Controllers.FilterActionInvoker.<InvokeAsync>d__44.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Mvc.Infrastructure.MvcRouteHandler.<RouteAsync>d__6.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Routing.Template.TemplateRoute.<RouteAsync>d__27.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Routing.RouteCollection.<RouteAsync>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.IISPlatformHandler.IISPlatformHandlerMiddleware.<Invoke>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Diagnostics.StatusCodePagesMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Microsoft.AspNet.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()

即使对文件是否存在进行了显式检查,它似乎也在窃听。我也可以手动确认文件存在。

也许我不明白什么是虚拟文件结果(文件方法返回这个)。在这里的文档中,它并没有真正描述它是什么。

我正在使用 ASP.NET 5 RC1。

虚拟文件结果文件存在时找不到文件

您要查找的方法PhysicalFile()

return PhysicalFile(fileName, FileUtility.GetContentType(fileName), info.Name);

请注意,不要对此使用调用方提供的路径。

VirtualFileResult类需要其构造函数中文件的虚拟路径。
这意味着您需要提供相对于wwwroot文件夹的路径,因为它使用 HostingEnvironment 的 WebRootFileProvider

    private IFileProvider GetFileProvider(IServiceProvider requestServices)
    {
        if (FileProvider != null)
        {
            return FileProvider;
        }
        var hostingEnvironment = requestServices.GetService<IHostingEnvironment>();
        FileProvider = hostingEnvironment.WebRootFileProvider;
        return FileProvider;
    }
}

检查 github 上的代码

File("index.html") 或 File("~/index.html")没有运气,Virtualfileresult 抛出了 NotFound。

我的解决方案是使用Microsoft.AspNetCore.Mvc.ControllerBase方法文件(流文件流...) :

public virtual FileStreamResult File(Stream fileStream, 
       string contentType, string fileDownloadName);

索引控制器示例:

 using System.IO;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Logging;
 public class IndexController : Controller
 {
    ILoggerFactory Logger;
    public IndexController(ILoggerFactory loggerFactory)
    {
        Logger = loggerFactory;
    }
    static string sep = Path.DirectorySeparatorChar.ToString();
    [HttpGet("/index")]
    [HttpGet("/")]
    public IActionResult Index()
    {
        var log = Logger.CreateLogger("trace");
        var path = $"{Startup.RootPath}{sep}index.html";
        log.LogWarning(path);
        Stream fileStream  = new System.IO.FileStream(path, FileMode.Open);
        return File(fileStream, "text/html");
    }
}
// AspnetCore version 1.1.1 :
// <TargetFramework>netcoreapp1.1</TargetFramework>
// <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />

您的 VirtualFileResult 必须是应用程序的 wwwroot 的相对路径。

return File("~/foo.js","text/javascript")

将指向wwwroot/foo.js