javascript - 将文件发送到浏览器/response.write 替代方案

标签 javascript asp.net vb.net vb.net-2010

在我的 aspx 页面上,我有一个动态创建的菜单,其中包含指向存储在 Oracle 数据库中的文档的链接。

当用户单击菜单中的链接时,它调用一个 JScript 函数,该函数在代码隐藏页面中调用 WebMethod 修饰的 vb.net 过程。此函数传递用于查询 Oracle 数据库的元素 ID,并返回相应的 blob 对象,即用户请求的文档。

当我测试它时,我将它连接到一个按钮,对所有内容进行硬编码,然后能够将文档返回到浏览器,并且没有任何问题。下面是我用来将 blob 对象返回给浏览器的内容。

Response.Clear()
Response.ClearContent()
Response.ClearHeaders()

Response.Buffer = True
Response.AddHeader("Content-Disposition", "attachment; filename=" + docname)
Response.ContentType = "application/pdf"

Response.BinaryWrite(bytes)

现在我已将代码移动到可调用方法中。我刚刚了解到我不能使用 Response 将我从数据库中提取的文件写入浏览器。或者,如果可以做到,我不知道该怎么做。下面是代码。

ASPX page.

 <%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/Site.Master" CodeBehind="FrmBookMain.aspx.vb" Inherits="ccc.com.FormsBook" %>

<%@ Register Assembly="Obout.Ajax.UI" Namespace="Obout.Ajax.UI.TreeView" TagPrefix="obout" %>
<%@ Register assembly="obout_Splitter2_Net" namespace="OboutInc.Splitter2" tagprefix="obspl" %>
<%@ Register assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" namespace="System.Web.UI" tagprefix="cc1" %>
<%@ Register assembly="obout_Interface" namespace="Obout.Interface" tagprefix="cc2" %>
<%@ Register assembly="obout_EasyMenu_Pro" namespace="OboutInc.EasyMenu_Pro" tagprefix="oem" %>
<%@ Register assembly="System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" namespace="System.Web.UI.HtmlControls" tagprefix="cc3" %>


<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<div style="width:900px; height:450px">


<obspl:Splitter ID="spl1" runat="server">
    
    <leftpanel>
        <content>
            <asp:PlaceHolder ID="placeHolder1" EnableViewState="false" runat="server"></asp:PlaceHolder>
        </content>
    </leftpanel>
   
    <RightPanel>
        <Content>
            <div class="tdText" style="width:400px;height:80%;padding-left:30px;padding-top:30px">
                        <h2>Document Repository</h2>
                        Choose a document from the left menu...
            </div>
        </Content>
    </RightPanel>
</obspl:Splitter>

</div>
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"/>
<script type="text/javascript" src="../Java/Frm_JScript.js"/> 

</asp:Content>

JavaScript Code

function GetDocument(src) {
 PageMethods.wbmGetDocument(src);
}

VB.net Module

Module modGetDoc_Frm

<WebMethod()>
    Public Sub wbmGetDocument(ByVal sID As String)

        Dim dr As OracleDataReader = Get_DataReader(sSql_GetDocument(sID))
        Dim blob As OracleBlob = dr.GetOracleBlob(1)

        Dim bytes(blob.Length) As Byte : blob.Read(bytes, 0, blob.Length)

        Dim doctype As String = dr(2).ToString()
        Dim docname As String = dr(3).ToString()
        
      *** Everything below won't work in module is there an alternative or what am I doing wrong***
        Response.Clear()
        Response.ClearContent()
        Response.ClearHeaders()
        Response.Buffer = True
        
        Response.AddHeader("Content-Disposition", "attachment; filename=" + docname)
        Response.ContentType = "application/pdf"
        Response.BinaryWrite(bytes)


    End Sub


End Module

修复

正如@Icarus 在下面所说,我添加了一个从 java 脚本调用它的 .ashx 页面,并允许它处理文件。这样做可以让您从代码隐藏访问响应流。 此链接帮助我更详细地了解 .ashx 页面 http://www.dotnetperls.com/ashx

JavaScript

function GetDocument(id) {
    window.open('FrmDocHandler.ashx?ID=' + id);
}

.ashx code

 Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

        Dim sID As String = context.Request.QueryString("id")

        Dim fileName As String
        Dim fileType As String
        Dim bytes() As Byte

        bytes = Get_Blob(fileName, fileType, sSql_GetDocument(sID))
        context.Response.Clear()
        'clear the content of the browser
        context.Response.ClearContent()
        context.Response.ClearHeaders()
        context.Response.Buffer = True

        context.Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName)

        context.Response.ContentType = GetMIMEType(fileType)

        context.Response.BinaryWrite(bytes)

最佳答案

你不能这样做的原因是因为你现在处于 XML HTTP 请求(更广为人知的 AJAX)的上下文中并且你不能将二进制数据直接写入响应,除非你使用 hack 或新的XMLHttpRequest2 中的功能已记录 here .

如果您不想诉诸 hack 或者冒着在某些浏览器中不受广泛支持的风险,一种替代方法是简单地 - 从 Javascript - 打开一个新窗口,并将文档 ID 作为参数传递到 url 中。像这样的东西:

function GetDocument(src) {
   window.open('FileHandler.ashx?docId='+src);
}

然后像现在一样流式传输 PDF。

FileHandler.ashx 可以是一个 Http 处理程序,或者如果您想保持简单,可以将其设为普通的 aspx 页面,从 Request.QueryString 获取 id 并流式传输 PDF。

关于javascript - 将文件发送到浏览器/response.write 替代方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23252603/

相关文章:

javascript - 在 Firefox 中的关闭选项卡按钮上叠加图标

vb.net - 如何确定启动应用程序时是否按下了 SHIFT 或 CTRL 键

vb.net - 是否可以更新列表(结构)中的元素?

c# - 有没有办法在 .net Framework 2 的 C# 应用程序中使用 linq?

javascript - 允许用户将多个不同的对象重新排序在一起

java - 使用ANTLR(或任何其他工具)编写术语重写解析器/表达式评估器

javascript - 如何将 Bootstrap 工具提示应用于动态生成的表

asp.net - 如何更改 swagger 文档基本网址?

javascript - 如何从被 GLSL 着色器置换的 Three.js 几何体中导出 OBJ?

c# - 如何在 MVC View 中更改显示格式