Вопрос или проблема
Это потоковое изображение из базы данных в верхней части _Layout чуть ниже навигационной панели, поэтому их нужно перезагружать каждый раз, когда пользователь переходит на новую страницу — но это очень медленно, почти одна секунда на изображение. Поэтому я решил их кэшировать и был очень удивлен, увидев, что нет заметной разницы — все еще почти одна секунда на изображение. Назовите меня растерянным?
Function ImageViewer(ImageId? As Integer, ImageType As String) As ActionResult
If Session("HOAID") Is Nothing Then
Return Content(BlankImage())
Else
If ImageId Is Nothing OrElse ImageId = 0 Then
Return Content(BlankImage())
Else
'Проверить, было ли кэшировано
Dim vKey As String = ImageId & "_" & Session("HOAID")
Dim vCache As MemoryCache = MemoryCache.Default
Dim vObject() As Byte = vCache.Get(vKey)
If Not vObject Is Nothing Then
Dim vMemStream As New IO.MemoryStream(vObject)
Dim vCacheImage As System.Drawing.Image = System.Drawing.Image.FromStream(vMemStream)
If ImageFormat.Jpeg.Equals(vCacheImage.RawFormat) Then
vCacheImage.Save(vMemStream, System.Drawing.Imaging.ImageFormat.Jpeg)
ElseIf ImageFormat.Png.Equals(vCacheImage.RawFormat) Then
Using PNGMemStream As New IO.MemoryStream
vCacheImage.Save(PNGMemStream, System.Drawing.Imaging.ImageFormat.Png)
PNGMemStream.WriteTo(Response.OutputStream)
End Using
ElseIf ImageFormat.Gif.Equals(vCacheImage.RawFormat) Then
vCacheImage.Save(vMemStream, System.Drawing.Imaging.ImageFormat.Gif)
End If
vMemStream.WriteTo(Response.OutputStream)
vMemStream.Close()
vMemStream.Dispose()
vMemStream = Nothing
HttpContext.ApplicationInstance.CompleteRequest()
'Конец возврата кэшированного изображения
Return View()
End If
Select Case ImageType
Case "Main"
ImageType = "Image_Main"
Case "Thumbnail"
ImageType = "Image_Thumbnail"
Case "Icon"
ImageType = "Image_Icon"
Case Else
Return Content(BlankImage())
End Select
If ImageId = 99999 Then
Return Content(BlankImage())
End If
Dim vImage() As Byte = Nothing
Dim vMIMEType As String = ""
Dim vObj As Object = Nothing
strSQL = "SELECT " & ImageType & ", Image_MIMEType FROM HOA3_Images WHERE Image_ID = " & ImageId
Using DS As DataSet = ReturnDataSet_Data(strSQL, Session("HOAID"), True)
For Each Row As DataRow In DS.Tables(0).Rows
vObj = Row(ImageType)
If vObj.Equals(DBNull.Value) Then
Return Content(BlankImage())
End If
vImage = Row(ImageType)
If vImage.Equals(DBNull.Value) Then
Return Content(BlankImage())
End If
vMIMEType = Row("Image_MIMEType")
Next
End Using
Response.Clear()
Response.BufferOutput = True
Dim vRandom As String = RandomGenerator(8)
Select Case vMIMEType.ToLower
Case ".jpg"
Response.ContentType = "image/jpeg"
Response.AppendHeader("content-disposition", "filename=" & Session("HOAID") & "_" & ImageId & ".jpeg")
Case ".jpeg"
Response.ContentType = "image/jpeg"
Response.AppendHeader("content-disposition", "filename=" & Session("HOAID") & "_" & ImageId & ".jpeg")
Case ".gif"
Response.ContentType = "image/gif"
Response.AppendHeader("content-disposition", "filename=" & Session("HOAID") & "_" & ImageId & ".gif")
Case ".png"
Response.ContentType = "image/png"
Response.AppendHeader("content-disposition", "filename=" & Session("HOAID") & "_" & ImageId & ".png")
End Select
Dim MemStream As New IO.MemoryStream(vImage)
Dim vRetImage As System.Drawing.Image = System.Drawing.Image.FromStream(MemStream)
Dim FileExt As String = vMIMEType.ToLower
Select Case FileExt
Case ".png"
'Файлы png необходимо записать обратно в память - другой формат!
Dim PNGMemstream As New IO.MemoryStream()
vRetImage.Save(PNGMemstream, System.Drawing.Imaging.ImageFormat.Png)
PNGMemstream.WriteTo(Response.OutputStream)
PNGMemstream.Close()
PNGMemstream.Dispose()
PNGMemstream = Nothing
Case ".gif"
vRetImage.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Gif)
Case ".jpeg"
vRetImage.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case ".jpg"
vRetImage.Save(Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg)
Case Else
Return Content(BlankImage())
End Select
Dim vPolicy As New CacheItemPolicy With {.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(10)}
vCache.Add(vKey, vImage, vPolicy)
MemStream.WriteTo(Response.OutputStream)
MemStream.Close()
MemStream.Dispose()
MemStream = Nothing
HttpContext.ApplicationInstance.CompleteRequest()
End If
End If
Return View()
End Function
Так что, должно быть, я делаю явную ошибку где-то! Но где?
Ответ или решение
Почему динамическая загрузка изображений происходит медленно и как это исправить
Загрузка изображений на веб-страницах — это важный аспект, который может существенно повлиять на пользовательский опыт. Если вы столкнулись с проблемой медленной загрузки динамических изображений из базы данных, это может быть вызвано несколькими факторами. В этом ответе мы рассмотрим возможные причины медленной загрузки изображений и предложим методы оптимизации.
1. Причины медленной загрузки изображений
1.1 Медленная передача данных
Скорость, с которой изображения загружаются, может зависеть от пропускной способности сети. Если ваш сервер или хостинг имеет низкую пропускную способность, время загрузки изображений может увеличиваться.
1.2 Проблемы с кэшированием
Хотя вы упомянули, что добавили кэширование, важно убедиться, что кэш правильно настроен. Если кэш не работает должным образом, это может привести к повторной загрузке изображений из базы данных, что увеличивает время их загрузки.
1.3 Неправильное использование потоков
Работа с потоками в .NET требует осторожности. Если вы не освобождаете ресурсы потока или неправильно обрабатываете их, это может привести к утечкам памяти и, как следствие, замедлению работы вашего приложения.
2. Оптимизация процесса загрузки изображений
2.1 Улучшение кэширования
В вашем коде имелись ошибки в кэшировании изображений. Убедитесь, что ключи кэша уникальны и будут корректно извлекаться. Используйте более эффективный способ кэширования изображений, например, на уровне сервера (Redis, Memcached или встроенные кэши веб-сервера).
2.2 Использование CDN
Рассмотрите возможность использования сети доставки контента (CDN). CDN может значительно уменьшить время загрузки изображений за счет географического распределения серверов и кэширования контента более близко к конечному пользователю.
2.3 Адаптивные изображения
Вместо загрузки одного и того же изображения для всех устройств, используйте различные размеры для разных экранов. Это может существенно уменьшить время загрузки для мобильных пользователей, которые не требуют загрузки тяжелых изображений.
3. Примеры кода для проверки
Вот несколько изменений, которые вы можете сделать в вашем коде, чтобы помочь улучшить производительность:
If vObject IsNot Nothing Then
' Извлечение изображения из кэша
Dim vMemStream As New MemoryStream(vObject)
Response.ContentType = GetMimeType(vCacheImage.RawFormat)
vMemStream.WriteTo(Response.OutputStream)
Return New EmptyResult()
End If
' Используйте правильную стратегию кэширования
Dim vPolicy As New CacheItemPolicy With {.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(10)}
vCache.Set(vKey, vImage, vPolicy)
4. Выводы
При решении проблемы медленной загрузки динамических изображений важно рассмотреть все цепочки обработки изображений — от базы данных до отображения на веб-странице. Убедитесь, что кэширование правильно настроено и что сервер имеет необходимую производительность. Также не забывайте о таких аспектах, как оптимизация изображений и использование современных технологий, таких как CDN, которые могут значительно улучшить общее время загрузки контента.
Эти изменения помогут не только оптимизировать процесс загрузки изображений, но и улучшить общий пользовательский опыт на вашем сайте.