Reputation: 82146
I have an annoying problem: I should show a PDF in the browser (inline-display, not download).
So far, with the code below, it works for internet explorer. But in google-chrome, it just downloads.
On the same server, a 3rd party application that does the same works fine.
I suppose the problem is the "appliction/octet-stream" that you see in the content-type header...
I find this rather annoying.
My code sets content-type application/pdf, and when I look at the actual headers sent, i see it is application/octet-stream...
According to https://superuser.com/questions/219870/how-to-open-pdf-in-chromes-integrated-viewer-without-downloading-it#
this is because the mime is octet-stream instead of application/pdf...
And I have just one question: Why ? Why ? Why ? (Why does it set octet-stream, not application/pdf as set in the code - See full code below)
Bonus question: Why is Transfer-Encoding chunked if i set Content-Length to the length of the byte-array ?
The funny thing is, it works fine on my local development server, so this seems to have something to do with the evils of IIS >= 7...
ashx:
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim baPDF As Byte() = GetPdfFromImage(Me.Data)
'context.Response.Write(COR.Tools.JSON.JsonHelper.Serialize(Me.Data(context)))
context.Response.Clear()
'context.Response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName)
context.Response.AddHeader("Content-Disposition", Portal.ASP.NET.GetContentDisposition("Drucken.pdf", "inline"))
context.Response.AddHeader("Content-Length", baPDF.Length.ToString())
' context.Response.ContentType = "application/msword"
' context.Response.ContentType = "application/octet-stream"
' https://superuser.com/questions/219870/how-to-open-pdf-in-chromes-integrated-viewer-without-downloading-it#
' context.Response.ContentType = "text/html"
context.Response.ContentType = "application/pdf"
context.Response.BinaryWrite(baPDF)
context.Response.Flush()
context.Response.End()
End Sub
' COR.ASP.NET.StripInvalidPathChars("") '
Public Shared Function StripInvalidPathChars(str As String) As String
Dim strReturnValue As String = Nothing
If str Is Nothing Then
Return strReturnValue
End If
Dim sb As System.Text.StringBuilder = New System.Text.StringBuilder()
Dim achrInvalidPathChars As Char() = System.IO.Path.GetInvalidPathChars()
For Each cThisChar As Char In str
Dim bIsValid As Boolean = True
For Each cInvalid As Char In achrInvalidPathChars
If cThisChar = cInvalid Then
bIsValid = False
Exit For
End If
Next cInvalid
If bIsValid Then
sb.Append(cThisChar)
End If
Next cThisChar
strReturnValue = sb.ToString()
sb = Nothing
Return strReturnValue
End Function ' StripInvalidPathChars '
Public Shared Function GetContentDisposition(ByVal strFileName As String) As String
Return GetContentDisposition(strFileName, "attachment")
End Function ' GetContentDisposition '
' http://www.iana.org/assignments/cont-disp/cont-disp.xhtml '
Public Shared Function GetContentDisposition(ByVal strFileName As String, ByVal strDisposition As String) As String
' http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http '
Dim contentDisposition As String
strFileName = StripInvalidPathChars(strFileName)
If String.IsNullOrEmpty(strDisposition) Then
strDisposition = "inline"
End If
If System.Web.HttpContext.Current IsNot Nothing AndAlso System.Web.HttpContext.Current.Request.Browser IsNot Nothing Then
If (System.Web.HttpContext.Current.Request.Browser.Browser = "IE" And (System.Web.HttpContext.Current.Request.Browser.Version = "7.0" Or System.Web.HttpContext.Current.Request.Browser.Version = "8.0")) Then
contentDisposition = strDisposition + "; filename=" + Uri.EscapeDataString(strFileName).Replace("'", Uri.HexEscape("'"c))
ElseIf (System.Web.HttpContext.Current.Request.Browser.Browser = "Safari") Then
contentDisposition = strDisposition + "; filename=" + strFileName
Else
contentDisposition = strDisposition + "; filename*=UTF-8''" + Uri.EscapeDataString(strFileName)
End If
Else
contentDisposition = strDisposition + "; filename*=UTF-8''" + Uri.EscapeDataString(strFileName)
End If
Return contentDisposition
End Function ' GetContentDisposition '
This is the header of the 3rd party application, where Chrome displays it fine
Upvotes: 1
Views: 779
Reputation: 82146
The solution is as simple as it is hideous.
Thanks to a coworker change, the code was in an ashx file directly, not in ashx.vb.
The good part of this is, one can modify the ashx on the server, even when you have a compiled web-application. The bad part is, this has the same effect of compile on the fly as a website project.
Consequently, when you just recompile the application and put the MyWebApplication.dll onto the server, this leaves the old ashx as is.
And since ASP.NET uses the code in the ashx rather than the compiled dll, it always uses the old code, as long as you don't update the ashx file, too.
Changed it now, and it began working immediately.
Now, that was a good one...
There never was a mistake in the code to begin with.
Upvotes: 1
Reputation: 1641
You need to clear the headers before setting the header you want.
From Microsoft's page about Response.Clear
.
The Clear method does not clear header information.
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim baPDF As Byte() = GetPdfFromImage(Me.Data)
context.Response.ClearHeaders()
context.Response.ContentType = "application/pdf"
... ' Cut for brevity
End Sub
Upvotes: 0