ASP.NET:为啥我得到的标题不是我设置的?

Posted

技术标签:

【中文标题】ASP.NET:为啥我得到的标题不是我设置的?【英文标题】:ASP.NET: Why do I get another header than I set?ASP.NET:为什么我得到的标题不是我设置的? 【发布时间】:2014-03-28 00:12:16 【问题描述】:

我有一个烦人的问题: 我应该在浏览器中显示 PDF(内联显示,而不是下载)。

到目前为止,使用下面的代码,它适用于 Internet Explorer。 但在 google-chrome 中,它只是下载。

在同一台服务器上,执行相同操作的第 3 方应用程序可以正常工作。 我想问题是您在内容类型标题中看到的“应用程序/八位字节流”......

我觉得这很烦人。 我的代码设置了内容类型 application/pdf,当我查看发送的实际标头时,我看到它是 application/octet-stream...

根据 https://superuser.com/questions/219870/how-to-open-pdf-in-chromes-integrated-viewer-without-downloading-it#

这是因为 mime 是 octet-stream 而不是 application/pdf...

我只有一个问题:为什么?为什么 ?为什么 ? (为什么它设置八位字节流,而不是代码中设置的 application/pdf - 请参阅下面的完整代码) 奖励问题:如果我将 Content-Length 设置为字节数组的长度,为什么传输编码会被分块?

有趣的是,它在我的本地开发服务器上运行良好,所以这似乎与 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://***.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 '

这是第 3 方应用程序的标题,Chrome 可以正常显示

【问题讨论】:

您是否真的在服务器上设置了正确的 MIME? 您是否查看过其他浏览器中的标题 - 它们是否显示应用程序/pdf? 您是否查看过本文中描述的问题? codeproject.com/Articles/671592/… 【参考方案1】:

您需要在设置所需的标题之前清除标题。

来自Microsoft's page 关于Response.Clear

Clear 方法不清除头信息。

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

【讨论】:

不,不是 ClearHeaders(),我前段时间已经试过了。【参考方案2】:

解决方案既简单又可怕。

感谢同事的更改,代码直接在 ashx 文件中,而不是在 ashx.vb 中。

这样做的好处是,即使您有一个已编译的 Web 应用程序,也可以修改服务器上的 ashx。 不好的部分是,这具有与网站项目一样的即时编译效果。

因此,当您重新编译应用程序并将 MyWebApplication.dll 放到服务器上时,旧的 ashx 将保持原样。

而且由于 ASP.NET 使用 ashx 中的代码而不是编译后的 dll,因此只要您不更新 ashx 文件,它总是使用旧代码。

现在更改它,它立即开始工作。 现在,那是一个很好的... 代码从一开始就没有错误。

【讨论】:

我的 VS2008 默认不会打开 .ashx 文件,即使您在解决方案资源管理器中双击 .ashx 文件,它也会打开 .ashx.vb 文件。必须采取一些措施才能打破这种方式(!)我假设您的同事现在热衷于使用代码隐藏。 @Andrew Morton:右键单击,然后选择“编辑标记”或其他名称。另一种方法是将文本复制到记事本窗口中,然后删除 .vb 文件。 噢,不,不要让每个人都知道如何获得它,否则他们都会使用“Vew Mrk*p”。我很尴尬地意识到有很多方法可以弄乱我的网站代码,但我自己还没有做到这一点。 ;) @Andrew Morton:关于这个问题,另一个好方法是压缩您的应用程序,将其复制到服务器上,用 windows 解压缩,然后将其复制到目标目录。在某些系统上,之后您会丢失 *.js 文件...

以上是关于ASP.NET:为啥我得到的标题不是我设置的?的主要内容,如果未能解决你的问题,请参考以下文章

这是错误的,为啥不是? ASP.NET MVC 视图包

总是使用 ASP.NET 服务器控件的子类?如果不是,为啥不呢?

为啥 Bootstrap 不允许我在 ASP.NET MVC 页面中的下拉菜单上设置边距?

为啥在 ASP.NET MVC 中使用 lambdas 而不是反射?

为啥在 ASP.NET MVC 中回发后模型为空

为啥我的 Asp.Net Core 日志中出现“不支持 POST 请求”?