【问题标题】:Dynamic file download buttons in VB .NETVB .NET 中的动态文件下载按钮
【发布时间】:2019-08-27 03:54:57
【问题描述】:

我在 VB NET 2005 Web 项目中有一个页面。在页面加载时,它从登录用户那里获取数据,查找该用户拥有的一组文档,并为每个文档创建一个“下载”按钮。目前,此按钮会打开一个流式传输文档的新窗口,但我们希望按钮本身触发下载。

我对此有一些选择,但它们看起来都有些老套,虽然我还没有找到任何好的解决方案,但这似乎应该是一个已解决的问题。

按钮在表单中(因此带有隐藏字段的回发是“hacky”选项之一)。

【问题讨论】:

    标签: asp.net vb.net download


    【解决方案1】:

    假设我有一个包含 3 列的 GridView:FilenameSize 和一个 Download 按钮。然后设置按钮的CommandNameCommandArgument。出于安全原因,使用用户的文档 ID 而不是像我一样使用完整路径名可能是一个更好的主意。您可以使用当前用户和文档ID的组合来获取真实文件。

    <asp:TemplateField HeaderText="Filename">
        <ItemTemplate>
            <asp:Label ID="lblFilename" runat="server" Text='<%# Bind("Filename") %>' />
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Size">
        <ItemTemplate>
            <asp:Label ID="lblSize" runat="server" Text='<%# Bind("Size") %>' />
        </ItemTemplate>
    </asp:TemplateField>
    <asp:TemplateField HeaderText="Download">
        <ItemTemplate>
            <asp:Button ID="btnDownload" runat="server" Text="Download"
                CommandName="Download" CommandArgument='<%# Eval("FullName") %>' />
        </ItemTemplate>
    </asp:TemplateField>
    

    这是我用来保存下载文件列表的类。此类的列表绑定到 GridView。

    Public Class MyFileInfo
        Public Property Filename As String
        Public Property Fullname As String
        Public Property Size As Long
    End Class
    

    最后是处理下载按钮的点击。我使用CommandNameCommandArgument 来传递单击的按钮以及需要向浏览器提供的文件。我使用流并在标题中使用正确的MIME type 写入浏览器。

    Protected Sub GridView1_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles GridView1.RowCommand
        If e.CommandName = "Download" Then
            DownloadFile(e.CommandArgument)
        End If
    End Sub
    
    Sub DownloadFile(filename As String)
        Using fs = New FileStream(filename, FileMode.Open)
            Response.BufferOutput = False
            Response.AddHeader("Content-Length", fs.Length.ToString())
            Response.AppendHeader("Content-Disposition", "attachment;filename=" & Path.GetFileName(filename))
            Response.ContentType = "application/msword"
    
            fs.Position = 0
            fs.CopyTo(Response.OutputStream)
            Response.Flush()
            Response.End()
        End Using
    End Sub
    

    完整代码(aspx):

    <%@ Page Language="vb" AutoEventWireup="false" CodeBehind="WebForm1.aspx.vb" Inherits="WebApplication1.WebForm1" %>
    
    <!DOCTYPE html>
    
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
                    <Columns>
                        <asp:TemplateField HeaderText="Filename">
                            <ItemTemplate>
                                <asp:Label ID="lblFilename" runat="server" Text='<%# Bind("Filename") %>' />
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Size">
                            <ItemTemplate>
                                <asp:Label ID="lblSize" runat="server" Text='<%# Bind("Size") %>' />
                            </ItemTemplate>
                        </asp:TemplateField>
                        <asp:TemplateField HeaderText="Download">
                            <ItemTemplate>
                                <asp:Button ID="btnDownload" runat="server" Text="Download"
                                    CommandName="Download" CommandArgument='<%# Eval("FullName") %>' />
                            </ItemTemplate>
                        </asp:TemplateField>
                    </Columns>
                </asp:GridView>
            </div>
        </form>
    </body>
    </html>
    

    完整代码(后面的代码):

    Imports System.IO
    
    Public Class WebForm1
        Inherits System.Web.UI.Page
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
            If Not IsPostBack Then BindGridList()
        End Sub
    
        Protected Sub GridView1_RowCommand(sender As Object, e As GridViewCommandEventArgs) Handles GridView1.RowCommand
            If e.CommandName = "Download" Then
                DownloadFile(e.CommandArgument)
            End If
        End Sub
    
        Sub BindGridList()
            GridView1.DataSource = GetFiles()
            GridView1.DataBind()
        End Sub
    
        Function GetFiles() As List(Of MyFileInfo)
            Dim listFileInfos = New List(Of MyFileInfo)
    
            Dim dirInfo = New DirectoryInfo(Server.MapPath("~/Data"))
            Dim fileInfos = dirInfo.GetFiles("*.doc")
            For Each fileInfo In fileInfos
                listFileInfos.Add(New MyFileInfo With {.Filename = fileInfo.Name, .Size = fileInfo.Length, .Fullname = fileInfo.FullName})
            Next
    
            Return listFileInfos
        End Function
    
        Sub DownloadFile(filename As String)
            Using fs = New FileStream(filename, FileMode.Open)
                Response.BufferOutput = False
                Response.AddHeader("Content-Length", fs.Length.ToString())
                Response.AppendHeader("Content-Disposition", "attachment;filename=" & Path.GetFileName(filename))
                Response.ContentType = "application/msword"
    
                fs.Position = 0
                fs.CopyTo(Response.OutputStream)
                Response.Flush()
                Response.End()
            End Using
        End Sub
    End Class
    
    Public Class MyFileInfo
        Public Property Filename As String
        Public Property Fullname As String
        Public Property Size As Long
    End Class
    

    【讨论】:

    • 完美,感谢您的回复。我觉得有点傻,不考虑对记录进行数据绑定,而不是在按下按钮后获取记录(这是当前的实现)。是的,我们使用 Guid 作为文件 ID,尽管在这个......我继承的东西中有很多有问题的设计决策。
    猜你喜欢
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 2017-12-03
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 2019-11-26
    相关资源
    最近更新 更多