我正在开发 ASP.NET Webforms 应用程序,我需要检索一些在 SQL Server 数据库上存储为
Blob
的 PDF 文件。到目前为止,我可以从应用程序中看到表格上的文件,但我无法通过单击按钮打开它们。读取byte[] array
的服务器端代码是这样的:
protected void btnOpenFile_Click(object sender, EventArgs e)
{
List<BinaryServer> binaryFiles = bs.BinariesServer.GetBinariesServer(Token);
Response.Clear();
Response.AppendHeader("Content-Disposition", "filename=Test.pdf");
Response.ContentType = "application/pdf";
Response.BinaryWrite(binaryFiles[0].Blob);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.SuppressContent = true;
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
有趣的是,在调试上述代码时,它执行得很好,但是
Application_Error()
中的 Global.asax.cs
事件被引发,并且没有文件被打开。
我检查了以下解决方案,但没有一个有用。
事实上,我真正想做的是在
ListView
中列出文件(不仅是 PDF,还包括 Excel、txt 等),每个文件都有一个下载按钮,但对于 PDF 情况,我更愿意打开它在新选项卡中而不是直接下载。
好吧,假设我们有这个标记 - 网格视图:
<asp:GridView ID="GridFiles" runat="server"
AutoGenerateColumns="False" ShowHeaderWhenEmpty="true"
CssClass="table table-hover" OnRowDataBound="GridFiles_RowDataBound"
DataKeyNames="ID"
>
<Columns>
<asp:BoundField DataField="FileName" HeaderText="FileName" />
<asp:BoundField DataField="UpLoaded" HeaderText="UpLoaded" ItemStyle-Width="175" />
<asp:TemplateField HeaderText="Preview" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:Image ID="imgPreview" runat="server" Height="80" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Download" ItemStyle-HorizontalAlign="Center" >
<ItemTemplate>
<asp:LinkButton ID="cmdDownLoad"
runat="server" CssClass="btn myshadow"
OnClick="cmdDownLoad_Click" style="margin-top:20px" >
<span aria-hidden="true" class="glyphicon glyphicon-cloud-download"></span>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Delete" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:LinkButton ID="cmdDelete"
runat="server" CssClass="btn myshadow" style="margin-top:20px"
OnClick="cmdDelete_Click">
<span aria-hidden="true" class="glyphicon glyphicon-trash"></span>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<script>
function newtab() {
var sURL = "ShowPdf.aspx"
window.open(sURL, '_blank');
}
</script>
请注意按钮单击 - 我使用了 LinkButton,因为我想要一个“图标”,但简单的标准 asp.net 按钮也可以工作。
因此,如果文件不是 pdf,那么我们就下载,或者打开其他页面。
所以,按钮单击事件如下所示:
protected void cmdDownLoad_Click(object sender, EventArgs e)
{
LinkButton myBut = (LinkButton)sender;
GridViewRow gRow = (GridViewRow)myBut.NamingContainer; // get current grid row
int PK = (int)GridFiles.DataKeys[gRow.RowIndex]["ID"];
SqlCommand cmdSQL = new SqlCommand("SELECT * FROM tblFiles WHERE ID = @ID");
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = PK;
DataTable dt = General.MyRstP(cmdSQL);
string strFile = dt.Rows[0]["FileName"].ToString();
if (Path.GetExtension(strFile).ToUpper() == ".PDF")
{
// This is a pdf, so setup pk for display page
Session["PK"] = PK;
string sJava = "newtab();";
ScriptManager.RegisterStartupScript(this.Page, Page.GetType(), "myjump", sJava, true);
}
else
{
string sMineType = MimeMapping.GetMimeMapping(strFile);
byte[] FileData = (byte[])dt.Rows[0]["FileB"];
Response.ContentType = sMineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + strFile);
Response.BinaryWrite(FileData);
Response.End();
}
}
所以,如果是pdf,那么我们设置PK值,并调用JavaScript例程在新选项卡上跳转到新页面。
新页面有以下代码:
protected void Page_Load(object sender, EventArgs e)
{
int PK = (int)Session["PK"];
SqlCommand cmdSQL = new SqlCommand("SELECT * FROM tblFiles WHERE ID = @ID");
cmdSQL.Parameters.Add("@ID", SqlDbType.Int).Value = PK;
DataTable dt = General.MyRstP(cmdSQL);
string strFile = dt.Rows[0]["FileName"].ToString();
string sMineType = MimeMapping.GetMimeMapping(strFile);
byte[] FileData = (byte[])dt.Rows[0]["FileB"];
Response.ContentType = sMineType;
Response.AddHeader("Content-Disposition", $"inline; filename={strFile}");
Response.BinaryWrite(FileData);
Response.End();
}
结果是这样的:
所以,并不是拉取二进制文件然后尝试在新页面上显示。
检查文件类型,如果是 PDF,则将数据库 PK 值保存到会话中,然后运行一些 JavaScript 在新选项卡中打开新页面,然后该页面将按照以下方式加载/显示 pdf上面。