文件存在时找不到VirtualFileResult文件

时间:2016-02-26 17:02:28

标签: c# asp.net-core asp.net-core-mvc filenotfoundexception

也许我不理解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()

即使对文件是否存在进行了明确的检查,它似乎也在喋喋不休。我也可以手动确认文件存在。

也许我不理解VirtualFileResult是什么(File方法返回此)。在文档here上,它并没有真正描述它是什么。

我正在使用ASP.NET 5 RC1。

4 个答案:

答案 0 :(得分:3)

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

    private IFileProvider GetFileProvider(IServiceProvider requestServices)
    {
        if (FileProvider != null)
        {
            return FileProvider;
        }

        var hostingEnvironment = requestServices.GetService<IHostingEnvironment>();
        FileProvider = hostingEnvironment.WebRootFileProvider;

        return FileProvider;
    }
}

检查github

上的代码

答案 1 :(得分:2)

运气不好(&#34; index.html&#34;)或文件(&#34;〜/ index.html&#34;),Virtualfileresult会抛出NotFound。

我的解决方案是使用Microsoft.AspNetCore.Mvc.ControllerBase 方法File(Stream fileStream ...):

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" />

答案 2 :(得分:1)

您要查找的方法是PhysicalFile()

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

当心,请勿为此使用呼叫者提供的路径。

答案 3 :(得分:0)

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

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

将指向wwwroot / foo.js