防止在 ImageResizer 中找不到文件时出现异常?

Prevent Exception on not found file in ImageResizer?

我已经为 ImageResizer 编写了自定义 VirtualPathProvider
public Stream GetStream(long id) 方法中,如果找不到文件,我会返回 Stream.Null

if (!File.Exists(absoluteFilePath)) return Stream.Null;

但是 ImageResizer 抛出如下发送给客户的异常:

<!DOCTYPE html>
<html>
    <head>
        <title>Source stream is empty; it has a length of 0. No bytes, no data. We can't work with this.</title>
        <meta name="viewport" content="width=device-width" />
        <style>
         body {font-family:"Verdana";font-weight:normal;font-size: .7em;color:black;} 
         p {font-family:"Verdana";font-weight:normal;color:black;margin-top: -5px}
         b {font-family:"Verdana";font-weight:bold;color:black;margin-top: -5px}
         H1 { font-family:"Verdana";font-weight:normal;font-size:18pt;color:red }
         H2 { font-family:"Verdana";font-weight:normal;font-size:14pt;color:maroon }
         pre {font-family:"Consolas","Lucida Console",Monospace;font-size:11pt;margin:0;padding:0.5em;line-height:14pt}
         .marker {font-weight: bold; color: black;text-decoration: none;}
         .version {color: gray;}
         .error {margin-bottom: 10px;}
         .expandable { text-decoration:underline; font-weight:bold; color:navy; cursor:hand; }
         @media screen and (max-width: 639px) {
          pre { width: 440px; overflow: auto; white-space: pre-wrap; word-wrap: break-word; }
         }
         @media screen and (max-width: 479px) {
          pre { width: 280px; }
         }
        </style>
    </head>

    <body bgcolor="white">

            <span><H1>Server Error in '/' Application.<hr width=100% size=1 color=silver></H1>

            <h2> <i>Source stream is empty; it has a length of 0. No bytes, no data. We can't work with this.</i> </h2></span>

            <font face="Arial, Helvetica, Geneva, SunSans-Regular, sans-serif ">

            <b> Description: </b>An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

            <br><br>

            <b> Exception Details: </b>ImageResizer.ImageProcessingException: Source stream is empty; it has a length of 0. No bytes, no data. We can't work with this.<br><br>

            <b>Source Error:</b> <br><br>

            <table width=100% bgcolor="#ffffcc">
               <tr>
                  <td>
                      <code>

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.</code>

                  </td>
               </tr>
            </table>

            <br>

            <b>Stack Trace:</b> <br><br>

            <table width=100% bgcolor="#ffffcc">
               <tr>
                  <td>
                      <code><pre>

[ImageProcessingException (0x80004005): Source stream is empty; it has a length of 0. No bytes, no data. We can&#39;t work with this.]
   ImageResizer.ImageBuilder.GetStreamFromSource(Object source, ResizeSettings settings, Boolean&amp; disposeStream, String&amp; path, Boolean&amp; restoreStreamPosition) +806
   ImageResizer.ImageBuilder.LoadImage(Object source, ResizeSettings settings, Boolean restoreStreamPos) +392
   ImageResizer.ImageBuilder.BuildJob(ImageJob job) +183
   ImageResizer.ImageBuilder.Build(ImageJob job) +242
   ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings, Boolean disposeSource, Boolean addFileExtension) +107
   ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings, Boolean disposeSource) +23
   ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings) +18
   ImageResizer.&lt;&gt;c__DisplayClass3.&lt;HandleRequest&gt;b__2(Stream stream) +151
   ImageResizer.Plugins.DiskCache.&lt;&gt;c__DisplayClasse.&lt;TryWriteFile&gt;b__d() +322
   ImageResizer.Plugins.DiskCache.LockProvider.TryExecute(String key, Int32 timeoutMs, LockCallback success) +333
   ImageResizer.Plugins.DiskCache.CustomDiskCache.TryWriteFile(CacheResult result, String physicalPath, String relativePath, ResizeImageDelegate writeCallback, DateTime sourceModifiedUtc, Int32 timeoutMs, Boolean recheckFS) +402
   ImageResizer.Plugins.DiskCache.CustomDiskCache.GetCachedFile(String keyBasis, String extension, ResizeImageDelegate writeCallback, DateTime sourceModifiedUtc, Int32 timeoutMs, Boolean asynchronous) +733
   ImageResizer.Plugins.DiskCache.DiskCache.Process(IResponseArgs e) +170
   ImageResizer.Plugins.DiskCache.DiskCache.Process(HttpContext context, IResponseArgs e) +35
   ImageResizer.InterceptModule.HandleRequest(HttpContext context, String virtualPath, NameValueCollection queryString, IVirtualFile vf) +1491
   ImageResizer.InterceptModule.CheckRequest_PostAuthorizeRequest(Object sender, EventArgs e) +870
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean&amp; completedSynchronously) +69
</pre></code>

                  </td>
               </tr>
            </table>

            <br>

            <hr width=100% size=1 color=silver>

            <b>Version Information:</b>&nbsp;Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.34209

            </font>

    </body>
</html>
<!-- 
[ImageProcessingException]: Source stream is empty; it has a length of 0. No bytes, no data. We can&#39;t work with this.
   at ImageResizer.ImageBuilder.GetStreamFromSource(Object source, ResizeSettings settings, Boolean& disposeStream, String& path, Boolean& restoreStreamPosition)
   at ImageResizer.ImageBuilder.LoadImage(Object source, ResizeSettings settings, Boolean restoreStreamPos)
   at ImageResizer.ImageBuilder.BuildJob(ImageJob job)
   at ImageResizer.ImageBuilder.Build(ImageJob job)
   at ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings, Boolean disposeSource, Boolean addFileExtension)
   at ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings, Boolean disposeSource)
   at ImageResizer.ImageBuilder.Build(Object source, Object dest, ResizeSettings settings)
   at ImageResizer.InterceptModule.<>c__DisplayClass3.<HandleRequest>b__2(Stream stream)
   at ImageResizer.Plugins.DiskCache.CustomDiskCache.<>c__DisplayClasse.<TryWriteFile>b__d()
   at ImageResizer.Plugins.DiskCache.LockProvider.TryExecute(String key, Int32 timeoutMs, LockCallback success)
   at ImageResizer.Plugins.DiskCache.CustomDiskCache.TryWriteFile(CacheResult result, String physicalPath, String relativePath, ResizeImageDelegate writeCallback, DateTime sourceModifiedUtc, Int32 timeoutMs, Boolean recheckFS)
   at ImageResizer.Plugins.DiskCache.CustomDiskCache.GetCachedFile(String keyBasis, String extension, ResizeImageDelegate writeCallback, DateTime sourceModifiedUtc, Int32 timeoutMs, Boolean asynchronous)
   at ImageResizer.Plugins.DiskCache.DiskCache.Process(IResponseArgs e)
   at ImageResizer.Plugins.DiskCache.DiskCache.Process(HttpContext context, IResponseArgs e)
   at ImageResizer.InterceptModule.HandleRequest(HttpContext context, String virtualPath, NameValueCollection queryString, IVirtualFile vf)
   at ImageResizer.InterceptModule.CheckRequest_PostAuthorizeRequest(Object sender, EventArgs e)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
-->

编辑:
实际上,如果文件不存在,我不想向客户发送任何内容。

问题似乎是您正在 return 一个 Null Stream 而不是 null。

区别很细微,但 Stream.Null 不是 null,它是一个长度为 0 的实际流(又名绝对空流)。这就是你得到那个例外的原因。简而言之:

Stream.Null != null

您的虚拟提供商应该 return 为 null,如下所示:

if (!File.Exists(absoluteFilePath)) return null;

如果您检查 source code,在第 253 行,当您 return null 时,您会看到 ImageResizer 抛出 FileNotFoundException。如何处理此异常取决于其他几个因素,但在大多数配置中,这意味着用户将收到适当的 404 HTTP 响应。

IVirtualImageProvider 具有具有以下签名的 FileExists 方法:

bool FileExists(string virtualPath, NameValueCollection queryString)

我必须正确实施它。如果它 returns 为假,ImageResizer returns 没有任何异常,没有找到文件。