EDN Admin
Well-known member
I have written a generic file serving handler in asp.net/vb.net - it has been working great. I recently moved to a windows 7 box and am now debugging under IIS7, and this is where the problems occure.
Whenever I serve a file to either FireFox or Chrome (IE8 works fine) from IIS 7, the download will fail.
<br/>
- In FireFox the error is "[some file name and path].part could not be saved, because the source file could not be read."<br/>
- In Chrome the error is "<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Error 330 (net::ERR_CONTENT_DECODING_FAILED): Unknown error."<br/>
- In IE8 it works fine
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px If I run the same code in IIS6, it works fine.<br/>
If I run the same code in the Visual Studio virtual web server, it works fine (on windows 7 or XP).
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px I am rather concerned about this as our production web server will soon be IIS7; which Im starting to really love, and would hate to revert to IIS6 just because
this wont work in IIS7.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Here is the code Im using..Ive tried a number of different patterns. It seems to always fail on the Flush() line with the error "System.Web.HttpException
= {"The remote host closed the connection. The error code is 0x80070040."}"
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px One thing I have noticed, if I move the flush statment to the finally clause or remove it all together; firefox will attempt to read the entire file - it appears
to be looping through the entire block of code just fine, until it hits the flush statement. If I remove the flush statment I still get an error and it still tries to read the entire file before asking me to save it.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px --Edit: I removed the flush and tested again; firfox thinks it downloaded a zero byte file.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Im assuming I just have some sort of header issue going on here, but Im at a loss at this point as to what that would be.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Any help would be appreciated.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px
<div style="background-color:white; color:black
<pre><span style="color:blue Imports System.Web
<span style="color:blue Imports System.Web.Services
<span style="color:blue Imports System.Data.SqlClient
<span style="color:blue Imports System.Configuration.ConfigurationManager
<span style="color:blue Public <span style="color:blue Class FileHandler
<span style="color:blue Implements System.Web.IHttpHandler
<span style="color:blue Sub ProcessRequest(<span style="color:blue ByVal context <span style="color:blue As HttpContext) <span style="color:blue Implements IHttpHandler.ProcessRequest
<span style="color:blue Dim _fid <span style="color:blue As <span style="color:blue String = context.Request.QueryString(<span style="color:#a31515 "fid")
<span style="color:blue If <span style="color:blue Not _fid <span style="color:blue Is <span style="color:blue Nothing <span style="color:blue AndAlso IsNumeric(_fid) <span style="color:blue Then
<span style="color:blue Dim r <span style="color:blue As IDataReader = GetfileByID(_fid)
<span style="color:blue If <span style="color:blue CType(r, SqlDataReader).HasRows <span style="color:blue Then
StreamData(r, context)
<span style="color:blue Else
context.Response.ContentType = <span style="color:#a31515 "text/plain"
context.Response.Write(<span style="color:#a31515 "Failed to retrieve file")
<span style="color:blue End <span style="color:blue If
<span style="color:blue Else
context.Response.ContentType = <span style="color:#a31515 "text/plain"
context.Response.Write(<span style="color:#a31515 "Invalid File ID")
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue Sub
<span style="color:blue Private <span style="color:blue Sub StreamData(<span style="color:blue ByVal r <span style="color:blue As IDataReader, <span style="color:blue ByVal context <span style="color:blue As HttpContext)
<span style="color:blue If r.Read <span style="color:blue Then
<span style="color:blue Dim dfi <span style="color:blue As <span style="color:blue New BO_DATASET_OUTPUT_FILE
dfi.Size = r.Item(<span style="color:#a31515 "Size")
dfi.ContentType = r.Item(<span style="color:#a31515 "ContentType")
dfi.Name = r.Item(<span style="color:#a31515 "Name")
context.Response.AddHeader(<span style="color:#a31515 "Content-Disposition", <span style="color:#a31515 "attachment;filename=" & dfi.Name & <span style="color:#a31515 ";")
context.Response.AddHeader(<span style="color:#a31515 "Content-Length", dfi.Size.ToString)
<span style="color:blue Dim dataOrdinal <span style="color:blue As <span style="color:blue Integer = r.GetOrdinal(<span style="color:#a31515 "Bytes")
<span style="color:blue If <span style="color:blue Not r(dataOrdinal) <span style="color:blue Is DBNull.Value <span style="color:blue Then
StreamByteArrayInChunks(r, dataOrdinal, context)
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue Sub
<span style="color:blue Private <span style="color:blue Sub StreamByteArrayInChunks(<span style="color:blue ByVal r <span style="color:blue As IDataReader, <span style="color:blue ByVal Ordinal <span style="color:blue As <span style="color:blue Integer, <span style="color:blue ByVal context <span style="color:blue As HttpContext)
<span style="color:blue Dim buffer(102400) <span style="color:blue As <span style="color:blue Byte
<span style="color:blue Dim index <span style="color:blue As <span style="color:blue Integer = 0
<span style="color:blue Try
<span style="color:blue While <span style="color:blue True
<span style="color:blue Dim <span style="color:blue count <span style="color:blue As <span style="color:blue Long = r.GetBytes(Ordinal, index, buffer, 0, buffer.Length)
<span style="color:blue If <span style="color:blue count = 0 <span style="color:blue Then
<span style="color:blue Exit <span style="color:blue While
<span style="color:blue Else
index = index + <span style="color:blue count
context.Response.BinaryWrite(buffer)
context.Response.Flush()
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue While
<span style="color:blue Catch ex <span style="color:blue As Exception
context.Response.Close()
<span style="color:blue Finally
r.Close()
context.Response.Close()
GC.Collect()
<span style="color:blue End <span style="color:blue Try
<span style="color:blue End <span style="color:blue Sub
<span style="color:blue Public <span style="color:blue Function GetfileByID(<span style="color:blue ByVal fid <span style="color:blue As <span style="color:blue Decimal) <span style="color:blue As IDataReader
<span style="color:blue Dim myConnecation <span style="color:blue As SqlConnection = <span style="color:blue New SqlConnection(AppSettings(<span style="color:#a31515 "fileStreamConn"))
myConnecation.Open()
<span style="color:blue Dim cmd <span style="color:blue As SqlCommand = <span style="color:blue New SqlCommand(<span style="color:#a31515 "dbo.SProc_DataSet_Output_File", myConnecation)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(<span style="color:#a31515 "@Action", SqlDbType.<span style="color:blue Decimal).Value = 4
cmd.Parameters.Add(<span style="color:#a31515 "@FileID", SqlDbType.<span style="color:blue Decimal).Value = fid
<span style="color:blue Dim r <span style="color:blue As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
<span style="color:blue Return r
<span style="color:blue End <span style="color:blue Function
<span style="color:blue ReadOnly <span style="color:blue Property IsReusable() <span style="color:blue As <span style="color:blue Boolean <span style="color:blue Implements IHttpHandler.IsReusable
<span style="color:blue Get
<span style="color:blue Return <span style="color:blue False
<span style="color:blue End <span style="color:blue Get
<span style="color:blue End <span style="color:blue Property
<span style="color:blue End <span style="color:blue Class
[/code]
View the full article
Whenever I serve a file to either FireFox or Chrome (IE8 works fine) from IIS 7, the download will fail.
<br/>
- In FireFox the error is "[some file name and path].part could not be saved, because the source file could not be read."<br/>
- In Chrome the error is "<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Error 330 (net::ERR_CONTENT_DECODING_FAILED): Unknown error."<br/>
- In IE8 it works fine
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px If I run the same code in IIS6, it works fine.<br/>
If I run the same code in the Visual Studio virtual web server, it works fine (on windows 7 or XP).
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px I am rather concerned about this as our production web server will soon be IIS7; which Im starting to really love, and would hate to revert to IIS6 just because
this wont work in IIS7.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Here is the code Im using..Ive tried a number of different patterns. It seems to always fail on the Flush() line with the error "System.Web.HttpException
= {"The remote host closed the connection. The error code is 0x80070040."}"
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px One thing I have noticed, if I move the flush statment to the finally clause or remove it all together; firefox will attempt to read the entire file - it appears
to be looping through the entire block of code just fine, until it hits the flush statement. If I remove the flush statment I still get an error and it still tries to read the entire file before asking me to save it.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px --Edit: I removed the flush and tested again; firfox thinks it downloaded a zero byte file.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Im assuming I just have some sort of header issue going on here, but Im at a loss at this point as to what that would be.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px Any help would be appreciated.
<span><span style="line-height:15px; font-family:Helvetica,Arial,sans-serif; font-size:13px
<div style="background-color:white; color:black
<pre><span style="color:blue Imports System.Web
<span style="color:blue Imports System.Web.Services
<span style="color:blue Imports System.Data.SqlClient
<span style="color:blue Imports System.Configuration.ConfigurationManager
<span style="color:blue Public <span style="color:blue Class FileHandler
<span style="color:blue Implements System.Web.IHttpHandler
<span style="color:blue Sub ProcessRequest(<span style="color:blue ByVal context <span style="color:blue As HttpContext) <span style="color:blue Implements IHttpHandler.ProcessRequest
<span style="color:blue Dim _fid <span style="color:blue As <span style="color:blue String = context.Request.QueryString(<span style="color:#a31515 "fid")
<span style="color:blue If <span style="color:blue Not _fid <span style="color:blue Is <span style="color:blue Nothing <span style="color:blue AndAlso IsNumeric(_fid) <span style="color:blue Then
<span style="color:blue Dim r <span style="color:blue As IDataReader = GetfileByID(_fid)
<span style="color:blue If <span style="color:blue CType(r, SqlDataReader).HasRows <span style="color:blue Then
StreamData(r, context)
<span style="color:blue Else
context.Response.ContentType = <span style="color:#a31515 "text/plain"
context.Response.Write(<span style="color:#a31515 "Failed to retrieve file")
<span style="color:blue End <span style="color:blue If
<span style="color:blue Else
context.Response.ContentType = <span style="color:#a31515 "text/plain"
context.Response.Write(<span style="color:#a31515 "Invalid File ID")
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue Sub
<span style="color:blue Private <span style="color:blue Sub StreamData(<span style="color:blue ByVal r <span style="color:blue As IDataReader, <span style="color:blue ByVal context <span style="color:blue As HttpContext)
<span style="color:blue If r.Read <span style="color:blue Then
<span style="color:blue Dim dfi <span style="color:blue As <span style="color:blue New BO_DATASET_OUTPUT_FILE
dfi.Size = r.Item(<span style="color:#a31515 "Size")
dfi.ContentType = r.Item(<span style="color:#a31515 "ContentType")
dfi.Name = r.Item(<span style="color:#a31515 "Name")
context.Response.AddHeader(<span style="color:#a31515 "Content-Disposition", <span style="color:#a31515 "attachment;filename=" & dfi.Name & <span style="color:#a31515 ";")
context.Response.AddHeader(<span style="color:#a31515 "Content-Length", dfi.Size.ToString)
<span style="color:blue Dim dataOrdinal <span style="color:blue As <span style="color:blue Integer = r.GetOrdinal(<span style="color:#a31515 "Bytes")
<span style="color:blue If <span style="color:blue Not r(dataOrdinal) <span style="color:blue Is DBNull.Value <span style="color:blue Then
StreamByteArrayInChunks(r, dataOrdinal, context)
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue Sub
<span style="color:blue Private <span style="color:blue Sub StreamByteArrayInChunks(<span style="color:blue ByVal r <span style="color:blue As IDataReader, <span style="color:blue ByVal Ordinal <span style="color:blue As <span style="color:blue Integer, <span style="color:blue ByVal context <span style="color:blue As HttpContext)
<span style="color:blue Dim buffer(102400) <span style="color:blue As <span style="color:blue Byte
<span style="color:blue Dim index <span style="color:blue As <span style="color:blue Integer = 0
<span style="color:blue Try
<span style="color:blue While <span style="color:blue True
<span style="color:blue Dim <span style="color:blue count <span style="color:blue As <span style="color:blue Long = r.GetBytes(Ordinal, index, buffer, 0, buffer.Length)
<span style="color:blue If <span style="color:blue count = 0 <span style="color:blue Then
<span style="color:blue Exit <span style="color:blue While
<span style="color:blue Else
index = index + <span style="color:blue count
context.Response.BinaryWrite(buffer)
context.Response.Flush()
<span style="color:blue End <span style="color:blue If
<span style="color:blue End <span style="color:blue While
<span style="color:blue Catch ex <span style="color:blue As Exception
context.Response.Close()
<span style="color:blue Finally
r.Close()
context.Response.Close()
GC.Collect()
<span style="color:blue End <span style="color:blue Try
<span style="color:blue End <span style="color:blue Sub
<span style="color:blue Public <span style="color:blue Function GetfileByID(<span style="color:blue ByVal fid <span style="color:blue As <span style="color:blue Decimal) <span style="color:blue As IDataReader
<span style="color:blue Dim myConnecation <span style="color:blue As SqlConnection = <span style="color:blue New SqlConnection(AppSettings(<span style="color:#a31515 "fileStreamConn"))
myConnecation.Open()
<span style="color:blue Dim cmd <span style="color:blue As SqlCommand = <span style="color:blue New SqlCommand(<span style="color:#a31515 "dbo.SProc_DataSet_Output_File", myConnecation)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.Add(<span style="color:#a31515 "@Action", SqlDbType.<span style="color:blue Decimal).Value = 4
cmd.Parameters.Add(<span style="color:#a31515 "@FileID", SqlDbType.<span style="color:blue Decimal).Value = fid
<span style="color:blue Dim r <span style="color:blue As SqlDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
<span style="color:blue Return r
<span style="color:blue End <span style="color:blue Function
<span style="color:blue ReadOnly <span style="color:blue Property IsReusable() <span style="color:blue As <span style="color:blue Boolean <span style="color:blue Implements IHttpHandler.IsReusable
<span style="color:blue Get
<span style="color:blue Return <span style="color:blue False
<span style="color:blue End <span style="color:blue Get
<span style="color:blue End <span style="color:blue Property
<span style="color:blue End <span style="color:blue Class
[/code]
View the full article