Я занимаюсь разработкой веб-сайта для просмотра книг, который берет довольно большие изображения (более 77 мегапикселей) и масштабирует их перед тем, как отправить изображение. Это в основном делает следующий алгоритм:
- Если запрошенная книга уже была кэширована, подайте кэшированные изображения.
- Если книга не была кэширована, добавьте книгу в наш пул потоков кэширования книг.
- Пул потоков кэширования книг добавляет страницу каждой книги в наш пул потоков кэширования страниц.
- Пул потоков кэширования страниц кэширует изображение (расположенное на сервере в нашей локальной сети), наполовину снова и снова уменьшая изображение до тех пор, пока мы не уменьшим кэшированные версии образа в 2, 4, 8, 16, 32 и 64 раз. .
Вот код, делящий пополам отдельное изображение. Обратите внимание на использование BitmapImage:
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
Несмотря на то, что исключение говорит «не удается найти указанный файл», я могу сразу перейти к тому месту, где находится базовое изображение, и открыть файл самостоятельно.
ПРИМЕЧАНИЕ. Чтобы уточнить, сервер, на котором размещены код и кэшированные изображения, не является сервером, на котором размещены базовые образы. Сервер кода захватывает файл через URI, например «\ servername \ path \ filename.jpg», с сервера базовых изображений.
После выполнения некоторых тестов исключения возникают только при попытке открыть изображения на нашем IIS-сервере через объект BitmapImage. Исключение в BitmapImage происходит, независимо от того, устанавливаю ли я путь к файлу через UriSource или создаю объект FileStream и устанавливаю для него свойство StreamSource для BitmapImage. Они не появляются, если файлы открываются через объект FileStream, и не возникают, если файлы открываются через консольное приложение. Консольное приложение, использующее объект BitmapImage, также запускается без проблем.
Итак, чтобы наконец задать мой вопрос, почему у сервера возникают проблемы с кэшированием этих изображений через ASP.NET, а у моей машины нет проблем?