Imports Microsoft.VisualBasic
Imports System.Web
Imports System.Text.RegularExpressions
Imports System.Text
Imports System.IO
Imports System.Web.Caching
Namespace ZipCM
''' <summary>
''' Our compressor class for miniying and concatenating javascript files and css files
''' </summary>
''' <remarks></remarks>
Public Class Compressor
Inherits System.IO.Stream
#Region " Properties "
#Region " Required Properties by the IO.Stream Interface "
Public Overrides ReadOnly Property Length() As Long
Get
End Get
End Property
Public Overrides Property Position() As Long
Get
End Get
Set(ByVal value As Long)
End Set
End Property
Public Overrides ReadOnly Property CanRead() As Boolean
Get
End Get
End Property
Public Overrides ReadOnly Property CanSeek() As Boolean
Get
End Get
End Property
Public Overrides ReadOnly Property CanWrite() As Boolean
Get
End Get
End Property
#End Region
#Region " Internal Properties "
Private HTML As String, FileCSS As String, FileJS As String
Private context As HttpContext
Private PageID As Long
Private Base As System.IO.Stream
#End Region
#End Region
#Region " Methods "
#Region " Public "
#Region " Required by IO.Stream "
Public Overrides Sub Flush()
End Sub
Public Overrides Function Read(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer) As Integer
Return Me.Base.Read(buffer, offset, count)
End Function
Public Overrides Function Seek(ByVal offset As Long, ByVal origin As System.IO.SeekOrigin) As Long
End Function
Public Overrides Sub SetLength(ByVal value As Long)
End Sub
#End Region
''' <summary>
''' Fire up our class passing in our Response Stream
''' </summary>
''' <param name="ResponseStream"></param>
''' <remarks></remarks>
Public Sub New(ByVal ResponseStream As System.IO.Stream)
' Just in case it does not exist, let's throw up ;)
If ResponseStream Is Nothing Then Throw New ArgumentNullException("ResponseStream")
' Set our Response to the IO.Stream
Me.Base = ResponseStream
End Sub
''' <summary>
''' We want to overwrite our default Write method so we can do our stuff
''' </summary>
''' <param name="buffer"></param>
''' <param name="offset"></param>
''' <param name="count"></param>
''' <remarks></remarks>
Public Overrides Sub Write(ByVal buffer() As Byte, ByVal offset As Integer, ByVal count As Integer)
' Get HTML code from the Stream
HTML = System.Text.Encoding.UTF8.GetString(buffer, offset, count)
'Compress and Concatenate the CSS
Me.CompressStyles(HTML)
'Compress and Concatenate the JS
Me.CompressJavascript(HTML)
' Send output, but replace some unneeded stuff first, like tabs, and multi-spaces
HTML = HTML.Replace(vbTab, String.Empty).Replace(" ", String.Empty).Replace(vbCrLf, String.Empty)
' Set the buffer to the Bytes gotten from our HTML
buffer = System.Text.Encoding.UTF8.GetBytes(HTML)
' Write It Out (not unlike 'Spit It Out - Slipknot'
Me.Base.Write(buffer, 0, buffer.Length)
End Sub
#End Region
#Region " Internal "
''' <summary>
''' Compress and Concatenate Our Style Sheets
''' </summary>
''' <param name="StrFile"></param>
''' <remarks></remarks>
Private Sub CompressStyles(ByVal StrFile As String)
Dim FilesM As MatchCollection, FileName As String
' Grab all references to stylesheets as they are in our HTML
FilesM = Regex.Matches(StrFile, "<link.*?href=""(.*?)"".*? />")
Dim M(FilesM.Count - 1) As String
' Now that we have all our files in a match collection,
' we'll loop through each file and put each line together into one string
For i As Long = 0 To M.Length - 1
M(i) = FilesM(i).Groups(1).Value
FileName = HttpContext.Current.Server.MapPath(M(i).Replace("/", "\"))
FileName = FileName.Replace("\\\", "\")
' Make sure the file exists locally, then read the entire thing to add into our string
If File.Exists(FileName) Then
Using objFile As New StreamReader(FileName)
FileCSS += objFile.ReadToEnd
objFile.Close()
End Using
' Now that we have our concatenated string,
' let's replace the unneeded stuff
' Comments
FileCSS = Regex.Replace(FileCSS, "/\*.+?\*/", "", RegexOptions.Singleline)
' 2 Spaces
FileCSS = FileCSS.Replace(" ", String.Empty)
' Carriage Return
FileCSS = FileCSS.Replace(vbCr, String.Empty)
' Line Feed
FileCSS = FileCSS.Replace(vbLf, String.Empty)
' Hard Return
FileCSS = FileCSS.Replace(vbCrLf, String.Empty)
' Tabs w/ a single space
FileCSS = FileCSS.Replace(vbTab, " ")
FileCSS = FileCSS.Replace("\t", String.Empty)
' Get rid of spaces next to the special characters
FileCSS = FileCSS.Replace(" {", "{")
FileCSS = FileCSS.Replace("{ ", "{")
FileCSS = FileCSS.Replace(" }", "}")
FileCSS = FileCSS.Replace("} ", "}")
FileCSS = FileCSS.Replace(" :", ":")
FileCSS = FileCSS.Replace(": ", ":")
FileCSS = FileCSS.Replace(", ", ",")
FileCSS = FileCSS.Replace("; ", ";")
FileCSS = FileCSS.Replace(";}", "}")
' Another comment
FileCSS = Regex.Replace(FileCSS, "/\*[^\*]*\*+([^/\*]*\*+)*/", "$1")
End If
Next
Dim tmpCt As Long = 0
' One more loop to get rid of the multiple references,
' and replace it with a sigle reference to our new and improved stylesheet file
For Each tmpS As Match In FilesM
tmpCt += 1
If tmpCt = FilesM.Count Then
' If our count = the number of matches then replace
StrFile = StrFile.Replace(tmpS.Groups(0).ToString(), "<link type=""text/css"" rel=""stylesheet"" href=""/Style.aspx"" />")
Else
' if not, just get rid of it
StrFile = StrFile.Replace(tmpS.Groups(0).ToString(), String.Empty)
End If
Next
FilesM = Nothing
' Need to put the New and Improved CSS string somewhere!
' What a better place for it, then the server cache
HttpContext.Current.Cache("CSS") = FileCSS
' We also need to return the improved HTML
HTML = StrFile
End Sub
''' <summary>
''' Compress Our Scripts
''' </summary>
''' <param name="StrFile"></param>
''' <remarks></remarks>
Private Sub CompressJavascript(ByVal StrFile As String)
Dim FilesM1 As MatchCollection, FileName As String
' Grab all references to script files as they are in our HTML
FilesM1 = Regex.Matches(StrFile, "<script.*?src=""(.*?)"".*?></script>")
Dim M1(FilesM1.Count - 1) As String
' Now that we have all our files in a match collection,
' we'll loop through each file and put each line together into one string
For j As Long = 0 To M1.Length - 1
M1(j) = FilesM1(j).Groups(1).Value
FileName = HttpContext.Current.Server.MapPath(M1(j).Replace("/", "\"))
FileName = FileName.Replace("\\\", "\")
' Make sure the file exists locally, then read the entire thing to add into our string
If File.Exists(FileName) Then
Using objFile1 As New StreamReader(FileName)
FileJS += objFile1.ReadToEnd
objFile1.Close()
End Using
' Now that we have our concatenated string,
' let's replace the unneeded stuff
' Comments
FileJS = Regex.Replace(FileJS, "(// .*?$)", "", RegexOptions.Multiline)
FileJS = Regex.Replace(FileJS, "(/\*.*?\*/)", "", RegexOptions.Multiline)
' 2 Spaces with 1 Space
FileJS = FileJS.Replace(" ", " ")
' Carriage Return
FileJS = FileJS.Replace(vbCr, vbLf)
' Hard Return w/ Line Feed
FileJS = FileJS.Replace(vbCrLf, vbLf)
' Tabs with a single space
FileJS = FileJS.Replace(vbTab, " ")
End If
Next
Dim tmpCt1 As Long = 0
' One more loop to get rid of the multiple references,
' and replace it with a sigle reference to our new and improved stylesheet file
For Each tmpS As Match In FilesM1
tmpCt1 += 1
If tmpCt1 = FilesM1.Count Then
' If our count = the number of matches then replace
StrFile = StrFile.Replace(tmpS.Groups(0).ToString(), "<script type=""text/javascript"" src=""/Script.aspx""></script>")
Else
' if not, just get rid of it
StrFile = StrFile.Replace(tmpS.Groups(0).ToString(), String.Empty)
End If
Next
FilesM1 = Nothing
' Need to put the New and Improved JS Somewhere!
' What a better place for it then the server cache
HttpContext.Current.Cache("JS") = FileJS
' Also need to return the New and Improved HTML
HTML = StrFile
End Sub
#End Region
#End Region
End Class
End Namespace
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
241:
242:
243:
244:
245:
246:
247:
248:
249:
250:
251:
252:
253:
254:
255:
256:
257:
258:
259:
260:
261:
262:
263:
264:
265:
266:
by: kevp75 on 2011-02-02 at 09:41:32ID: 23418
What I found was that even though there would be no Exceptions thrown, the Script.aspx, and Style.aspx would have no response.
To cure the issue, I simply moved the heavy processing into the Page_Init event, and kept the Response.Filter in the Page_Load event, and it worked perfectly...
So, What I would suggest is a slight change to the first Default.aspx page above.
Copy everything from Page_Load event except the Response.Filter line and paste it into Page_Init event.
~ Happy Coding!