我正在开发一个书籍浏览网站,它会在提供图片之前将较大的图片(高达77+百万像素)进行缩放。它基本上执行以下算法:
尽管异常显示“找不到指定的文件”,但我可以直接进入基础图像所在的位置并打开文件。
注意:搭载代码和缓存图像的服务器不是搭载基础图像的服务器。代码服务器通过类似“\servername\path\filename.jpg”的URI从基础图像服务器获取文件。
运行一些测试后,只有在尝试通过BitmapImage对象打开我们的IIS服务器上的图像时才会发生异常。无论我是通过UriSource设置文件路径还是创建一个FileStream对象并将其设置为BitmapImage的StreamSource属性,BitmapImage中的异常都会发生。如果通过FileStream对象打开文件,则不会发生异常,如果通过控制台应用程序打开文件也不会发生异常。使用BitmapImage对象的控制台应用程序也可以正常运行。
因此,最终问我的问题是,为什么服务器在通过ASP.NET缓存这些图像时出现问题,而我的开发机器没有问题?
- 如果已经缓存了所请求的书籍,请提供缓存的图像。
- 如果尚未缓存该书籍,则将该书籍添加到我们的书籍缓存线程池中。
- 书籍缓存线程池将每个书籍页面添加到我们的页面缓存线程池中。
- 页面缓存线程池通过反复缩小图像的大小,将位于局域网服务器上的图像缓存为2x、4x、8x、16x、32x和64x的版本。
Private Shared Function HalveImage(ByVal baseImagePath As String, ByVal baseWidth As Integer, ByVal baseHeight As Integer, ByVal newImagePath As String) As BitmapImage
Dim bi As New BitmapImage
With bi
.BeginInit()
.UriSource = New Uri(baseImagePath)
.DecodePixelWidth = baseWidth / 2 'only seting one DecodePixelXXX property preserves the aspect ratio
.EndInit()
End With
Dim enc As New System.Windows.Media.Imaging.JpegBitmapEncoder
With enc
.QualityLevel = 50
.Frames.Add(BitmapFrame.Create(bi))
End With
Using stream As New IO.FileStream(newImagePath, IO.FileMode.Create)
enc.Save(stream)
End Using
Return bi
End Function
这段代码在我的开发机上运行得很好,但是当我把它安装到服务器上时,服务器会突然停止缓存图片,即使已经缓存了数百张。网站的其余部分仍然正常工作。我们发现,页面缓存代码最终每次尝试创建BitmapImage对象时都会抛出此异常:
System.ComponentModel.Win32Exception: The system cannot find the file specified
at MS.Win32.UnsafeNativeMethods.RegisterClassEx(WNDCLASSEX_D wc_d)
at MS.Win32.HwndWrapper..ctor(Int32 classStyle, Int32 style, Int32 exStyle, Int32 x, Int32 y, Int32 width, Int32 height, String name, IntPtr parent, HwndWrapperHook[] hooks)
at MS.Win32.MessageOnlyHwndWrapper..ctor()
at System.Windows.Threading.Dispatcher..ctor()
at System.Windows.Threading.Dispatcher.get_CurrentDispatcher()
at System.Windows.Freezable..ctor()
at System.Windows.Media.Imaging.BitmapSource..ctor(Boolean useVirtuals)
at System.Windows.Media.Imaging.BitmapImage..ctor()
at RemoteFSTester.PageCachingThreadPool.WICResizer.CachePage(String id, Int32 item, Int32 index) in C:\Users\[...]\PageCachingThreadPool.vb:line 127
at RemoteFSTester.PageCachingThreadPool.CachePage(String id, Int32 item, Int32 index) in C:\Users\[...]\PageCachingThreadPool.vb:line 103
at RemoteFSTester.PageCachingThreadPool.WorkerMethod(PriorityThreadPoolDelegateArgs args) in C:\Users\[...]\PageCachingThreadPool.vb:line 91
at MDSA.Util.PriorityThreadpool.PriorityThreadPoolBase.Thread_DoWork(PriorityThreadPoolDelegateArgs args) in C:\Users\[...]\PriorityThreadPoolBase.vb:line 199
尽管异常显示“找不到指定的文件”,但我可以直接进入基础图像所在的位置并打开文件。
注意:搭载代码和缓存图像的服务器不是搭载基础图像的服务器。代码服务器通过类似“\servername\path\filename.jpg”的URI从基础图像服务器获取文件。
运行一些测试后,只有在尝试通过BitmapImage对象打开我们的IIS服务器上的图像时才会发生异常。无论我是通过UriSource设置文件路径还是创建一个FileStream对象并将其设置为BitmapImage的StreamSource属性,BitmapImage中的异常都会发生。如果通过FileStream对象打开文件,则不会发生异常,如果通过控制台应用程序打开文件也不会发生异常。使用BitmapImage对象的控制台应用程序也可以正常运行。
因此,最终问我的问题是,为什么服务器在通过ASP.NET缓存这些图像时出现问题,而我的开发机器没有问题?