c# - 如何压缩 ASP.NET 中的特定页面

标签 c# asp.net c#-4.0 compression microsoft-ajax

我的 Web 应用程序在某些页面中使用了 Ms Ajax(脚本管理器、更新面板...)。在这些页面中,我不能使用压缩,因为它与 *.axd 文件冲突。

如何压缩网络应用程序中的特定页面?

最佳答案

我使用 Http 模块来处理我的压缩。我无法对我的其中一个站点使用新的 IIS 压缩,因为它位于共享主机上并且它们没有启用 IIS 压缩。我还有一个自定义的 web.config 部分,我可以在其中排除特定的文件路径,如:

如果你想要模块的代码,请告诉我。我也可以发帖。一个类实际上执行压缩,而我使用其他 3 个类来处理自定义 web.config 部分。

  <RiderDesign>
    <HttpCompressionSettings compressionOn="true">
      <includedFileTypes>
        <add value="text/html"/>
        <add value="text/xhtml"/>
      </includedFileTypes>
      <excludedFilePaths>
        <add value="~/demos/partialpageupdates.aspx"/>
        <add value="~/demos/inlinetextedit.aspx"/>
      </excludedFilePaths>
    </HttpCompressionSettings
 </RiderDesign>

只需指定要排除的页面,它们不会被压缩。

我的压缩模块如下:

Imports System.Web
Imports System.IO
Imports System.Net
Imports System.IO.Compression

Namespace RiderDesign.FrameworkV4.HttpModule

    Public NotInheritable Class HttpCompressionModule
        Implements IHttpModule
        Private Shared GZIP As String = "gzip"
        Private Shared DEFLATE As String = "deflate"

        Private Shared ENCODING_TYPE As String = "encodingType"
        Private Shared CONTENT_TYPE As String = "contentType"
        Private MARK As String = "passedModule"
        Dim HttpState As HttpCompressionConfigStateModule
        Sub Dispose() Implements IHttpModule.Dispose
        End Sub
        Sub Init(ByVal context As HttpApplication) Implements IHttpModule.Init

            If HttpCompressionConfigModule.GetConfig().CompressionOn = True Then
                ' Use for any other then WebResource
                AddHandler context.PostReleaseRequestState, AddressOf context_PostReleaseRequestState
            End If

            If HttpCompressionConfigModule.GetConfig().CompressionOn = True Then
                ' Use only for WebResource.axd files
                AddHandler context.BeginRequest, AddressOf context_BeginRequest
                AddHandler context.EndRequest, AddressOf context_EndRequest
            End If
        End Sub 'IHttpModule.Init

        Sub context_PostReleaseRequestState(ByVal sender As Object, ByVal e As EventArgs)
            Dim app As HttpApplication = CType(sender, HttpApplication) '

            If TypeOf app.Context.CurrentHandler Is System.Web.UI.Page And app.Request("HTTP_X_MICROSOFTAJAX") Is Nothing Then
                Dim FilePath As String
                Dim FilePaths As List(Of String) = New List(Of String)

                For Each Me.HttpState In HttpCompressionConfigModule.GetConfig().ExcludedFilePaths
                    FilePaths.Add(String.Format("{0}", HttpState.Value))
                Next HttpState
                FilePath = String.Join(", ", FilePaths.ToArray())

                Dim ContentTypes As String
                Dim FileTypes As List(Of String) = New List(Of String)
                Dim state As HttpCompressionConfigStateModule
                For Each state In HttpCompressionConfigModule.GetConfig().IncludedFileTypes
                    FileTypes.Add(String.Format("{0}", state.Value))
                Next state
                ContentTypes = String.Join(", ", FileTypes.ToArray())


                ' Check if the path is not excluded.
                If FilePath.Contains(app.Request.AppRelativeCurrentExecutionFilePath) Then
                    Return
                End If
                ' Check if the mime type is not excluded. (Use to exclude pages that generate specific mime type (such image or Excel...))
                If Not ContentTypes.Contains(app.Response.ContentType) Then
                    Return
                End If
                ' Check if GZIP is supported by the client
                If IsGzipEncodingSupported() Then
                    app.Response.Filter = New GZipStream(app.Response.Filter, CompressionMode.Compress)
                    SetEncodingType(GZIP)
                    ' Check if DEFLATE is supported by the client 

                Else
                    If IsDeflateEncodingSupported() Then
                        app.Response.Filter = New DeflateStream(app.Response.Filter, CompressionMode.Compress)
                        SetEncodingType(DEFLATE)
                    End If
                End If
            End If
        End Sub


        Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
            Dim app As HttpApplication = CType(sender, HttpApplication) '
            '
            ' Check if the current request is WebResource.axd
            If app.Request.Path.Contains("WebResource.axd") Then
                SetCachingHeaders(app)

                If app.Context.Request.QueryString(MARK) Is Nothing Then
                    app.CompleteRequest()
                End If
            End If
        End Sub 'context_BeginRequest



        Sub context_EndRequest(ByVal sender As Object, ByVal e As EventArgs)
            Dim app As HttpApplication = CType(sender, HttpApplication) '

            If app.Request.Path.Contains("WebResource.axd") And app.Context.Request.QueryString(MARK) Is Nothing Then
                Dim cacheKey As String = app.Request.QueryString.ToString()

                If app.Application(cacheKey) Is Nothing Then
                    CompressedIntoCache(app, cacheKey)
                End If

                SetEncodingType(CStr(app.Application((cacheKey + ENCODING_TYPE))))
                app.Context.Response.ContentType = CStr(app.Application((cacheKey + CONTENT_TYPE)))
                app.Context.Response.BinaryWrite(CType(app.Application(cacheKey), Byte()))
            End If
        End Sub 'context_EndRequest



        Private Sub CompressedIntoCache(ByVal app As HttpApplication, ByVal cacheKey As String)
            'Mark the current request by adding QueryString parameter.
            Dim request As HttpWebRequest = CType(WebRequest.Create((app.Context.Request.Url.OriginalString + "&" + MARK + "=1")), HttpWebRequest)
            request.Credentials = CredentialCache.DefaultNetworkCredentials
            Using response As HttpWebResponse = CType(request.GetResponse, HttpWebResponse)

                If (True) Then
                    ' We getting the response stream, that raise again the 'BeginRequest' event (that why we marked the request)
                    Dim responseStream As Stream = response.GetResponseStream()

                    Dim contentType As String = response.ContentType.ToLower()

                    ' Not a javascript or css content.
                    ' We compress only WebResources that are Javascript or css file.
                    ' The problem is, that we can know the content type only after we got the response. TODO: find a better solution
                    ' for non CSS or JS content
                    If Not IsContentSupported(contentType) Then
                        ' Set the response type
                        app.Context.Response.ContentType = contentType

                        ' Send the file to the client without compression
                        StreamCopy(responseStream, app.Response.OutputStream)
                        responseStream.Dispose()
                        app.Context.Response.End()
                        Return
                    End If

                    ' Copy the response stream into memory stream, so we can convert it into byte[] easly.
                    Dim dataStream As New MemoryStream()
                    StreamCopy(responseStream, dataStream)
                    responseStream.Dispose()

                    ' Convert the response into byte[]
                    Dim data As Byte() = dataStream.ToArray()
                    dataStream.Dispose()
                    Dim encodingType As String = String.Empty

                    Using memstream As MemoryStream = New MemoryStream
                        Dim compress As Stream = Nothing

                        ' Choose the compression type and make the compression
                        If IsGzipEncodingSupported() Then
                            compress = New GZipStream(memstream, CompressionMode.Compress)
                            encodingType = GZIP
                        Else
                            If IsDeflateEncodingSupported() Then
                                compress = New DeflateStream(memstream, CompressionMode.Compress)
                                encodingType = DEFLATE
                            End If
                        End If
                        compress.Write(data, 0, data.Length)
                        compress.Dispose()

                        app.Application.Lock()
                        app.Application.Add(cacheKey, memstream.ToArray())
                        app.Application.Add(cacheKey + ENCODING_TYPE, encodingType)
                        app.Application.Add(cacheKey + CONTENT_TYPE, response.ContentType)
                        app.Application.UnLock()

                    End Using
                End If
            End Using

        End Sub 'CompressedIntoCache




        Private Shared Sub StreamCopy(ByVal input As Stream, ByVal output As Stream)
            Dim buffer(2048) As Byte
            Dim read As Integer
            Do
                read = input.Read(buffer, 0, buffer.Length)
                output.Write(buffer, 0, read)
            Loop While read > 0
        End Sub 'StreamCopy

        Private Shared Sub SetCachingHeaders(ByVal app As HttpApplication)
            Dim etag As String = """" + app.Context.Request.QueryString.ToString().GetHashCode().ToString() + """"
            Dim incomingEtag As String = app.Request.Headers("If-None-Match")

            app.Response.Cache.VaryByHeaders("Accept-Encoding") = True
            app.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(365))
            app.Response.Cache.SetCacheability(HttpCacheability.Public)
            app.Response.Cache.SetLastModified(DateTime.Now.ToUniversalTime().AddDays(-1))
            app.Response.Cache.SetETag(etag)

            If [String].Compare(incomingEtag, etag) = 0 Then
                app.Response.StatusCode = CInt(HttpStatusCode.NotModified)
                app.Response.End()
            End If
        End Sub 'SetCachingHeaders


        Private Shared Function IsBrowserSupported() As Boolean
            ' Because bug in Internet Explorer 6
            Return Not (HttpContext.Current.Request.UserAgent Is Nothing Or HttpContext.Current.Request.UserAgent.Contains("MSIE 6"))
        End Function 'IsBrowserSupported


        Private Shared Function IsEncodingSupported() As Boolean
            Return IsGzipEncodingSupported() Or IsDeflateEncodingSupported()
        End Function 'IsEncodingSupported

        Private Shared Function IsGzipEncodingSupported() As Boolean
            Return Not (HttpContext.Current.Request.Headers("Accept-encoding") Is Nothing) And HttpContext.Current.Request.Headers("Accept-encoding").Contains(GZIP)
        End Function 'IsGzipEncodingSupported

        Private Shared Function IsDeflateEncodingSupported() As Boolean
            Return Not (HttpContext.Current.Request.Headers("Accept-encoding") Is Nothing) And HttpContext.Current.Request.Headers("Accept-encoding").Contains(DEFLATE)
        End Function 'IsDeflateEncodingSupported

        Private Shared Sub SetEncodingType(ByVal encoding As String)
            HttpContext.Current.Response.AppendHeader("Content-encoding", encoding)
        End Sub 'SetEncodingType

        Private Shared Function IsContentSupported(ByVal contentType As String) As Boolean
            If contentType.Contains("text/css") Or contentType.Contains("javascript") Then
                Return True
            End If
            Return False
        End Function
    End Class
End Namespace

关于c# - 如何压缩 ASP.NET 中的特定页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8434881/

相关文章:

c# - 如果用户在hangman c#中猜测正确,如何显示用户的输入

javascript - 使用 ASP.NET WEB 表单在母版页中获取 JavaScript 错误

.net - 如何修复 Delphi Prism ASP.NET 错误 : "Parser Error Message: ' Oxygene' is not a supported language"

asp.net-mvc - List<string> 的编辑器模板

c# - 图像隐写术

c# - 插入图像作为多边形内容

c# - 建立恒定的层次结构

c# - 是否可以在两个项目中声明一个部分类

c# - 查找内存泄漏

c# - 选择对象并添加到列表 linq c#