WebForm 无法使用文件列表填充按钮命令参数?
WebForm can't populate button command argument with list of files?
我已经有很长时间没有使用 WebForms 了,但我不得不更新一个旧网站。我正在尝试制作一个页面,允许用户将文件下载到他们的机器上。我可以获得目录中的文件列表并将其显示在 table 中,但是,我试图将文件名分配给按钮的命令参数,以便我知道名称要在按钮事件中获取的文件。我似乎无法找到从文件夹对象中获取值以填充命令参数的正确方法。没有错误,它只是空白。有什么建议吗?
var listFiles = dir.GetFiles();
<%
foreach(var file in listFiles) { %>
<tr>
<td> </td>
<td><%= file.Name %></td>
<td><%= file.Length %></td>
<td><%= file.CreationTime.ToString("MM/dd/yyyy HH:mm") %></td>
<td>
<asp:LinkButton ID="btnDownload" runat="server"
CommandArgument='<%#Eval("file.Name") %>'
CommandName="DownloadTechFile"
OnCommand="DownloadFile"
ToolTip="Downloaded file">
<span aria-hidden="true" class="fa fa-download"></span>
</asp:LinkButton>
</td>
</tr>
<% } %>
protected void DownloadFile(object sender, CommandEventArgs e)
{
Alert.Hide();
var fileName = e.CommandArgument.ToString();
var fileFullPath = Path.Combine(FileFolderPath, fileName);
if (string.IsNullOrWhiteSpace(fileName) == false)
{
WebClient req = new WebClient();
HttpResponse response = HttpContext.Current.Response;
try
{
response.Clear();
response.ClearContent();
response.ClearHeaders();
response.Buffer = true;
response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
byte[] data = req.DownloadData(fileFullPath);
//byte[] data = req.DownloadData(Server.MapPath(fileFullPath));
response.BinaryWrite(data);
response.End();
Alert.Show(AlertType.Success, "File downloaded.");
}
catch (Exception ex)
{
logger.Error("Error downloading file from {0}. {1} | {2} | {3}", fileFullPath, ex.Message, ex.StackTrace, ex.InnerException);
Alert.Show(AlertType.Error, string.Format("Error trying to download file: {0}", fileName));
}
}
}
更新:
这是我想到的,以防其他人可以使用它。
<asp:GridView ID="gvFiles" runat="server" AutoGenerateColumns="false" CssClass="table borderless" HeaderStyle-CssClass="fileheader">
<Columns>
<asp:BoundField DataField="FileName" HeaderText="File Name" />
<asp:BoundField DataField="FileSize" HeaderText="File Size" />
<asp:BoundField DataField="Date" HeaderText="Created On" />
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:LinkButton ID="btnDownload" runat="server"
CommandArgument='<%# Eval("FileName") %>'
OnClick="DownloadFile"
ToolTip="Downloaded file">
<span aria-hidden="true" class="fa fa-download"></span>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
void LoadGrid()
{
// create a table for the files, populate, and then bind.
DataTable dtFiles = new DataTable();
dtFiles.Columns.Add("Date", typeof(string));
dtFiles.Columns.Add("FileSize", typeof(string));
dtFiles.Columns.Add("FileName", typeof(string));
DirectoryInfo fileDirectory = new DirectoryInfo(FileFolderPath);
foreach (FileInfo file in fileDirectory.GetFiles("*.txt"))
{
DataRow dr = dtFiles.NewRow();
dr["Date"] = file.CreationTime.ToString("MM/dd/yyyy HH:mm");
dr["FileSize"] = Utility.GetBytesReadable(file.Length);
dr["FileName"] = file.Name;
dtFiles.Rows.Add(dr);
}
dtFiles.DefaultView.Sort = "Date DESC";
gvFiles.DataSource = dtFiles;
gvFiles.DataBind();
}
protected void DownloadFile(object sender, EventArgs e)
{
var fileName = (sender as LinkButton).CommandArgument;
var fileFullPath = Path.Combine(FileFolderPath, fileName);
string mineType = MimeMapping.GetMimeMapping(fileFullPath);
if (string.IsNullOrWhiteSpace(fileName) == false)
{
byte[] binFile = File.ReadAllBytes(fileFullPath);
Response.ContentType = mineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
Response.BinaryWrite(binFile);
Response.End();
}
}
你可以说使用 gridview,这样说:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" CssClass="table">
<Columns>
<asp:BoundField DataField="File Name" HeaderText="File" />
<asp:BoundField DataField="Date" HeaderText="Date" />
<asp:BoundField DataField="File Size" HeaderText="Size" />
<asp:TemplateField HeaderText="Select" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" CssClass="btn btn-default"
NavigateUrl='<%# Eval("Path") %>' >Down Load</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
后面的代码可以是这样的:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
// create a table for the files
DataTable MyTable = new DataTable();
MyTable.Columns.Add("Date", typeof(string));
MyTable.Columns.Add("File Size", typeof(string));
MyTable.Columns.Add("File Name", typeof(string));
MyTable.Columns.Add("Path", typeof(string));
string strURLFolder = "~/Content/Animals/";
string strFolder = Server.MapPath(strURLFolder);
DirectoryInfo MyDir = new DirectoryInfo(strFolder);
FileInfo[] MyFiles = MyDir.GetFiles("*.*");
foreach (FileInfo MyFile in MyDir.GetFiles("*.*"))
{
DataRow OneRow = MyTable.NewRow();
OneRow["Date"] = MyFile.LastAccessTime;
OneRow["File Size"] = (MyFile.Length / 1024).ToString() + " KB";
OneRow["File Name"] = MyFile.Name;
OneRow["Path"] = strURLFolder + MyFile.Name;
MyTable.Rows.Add(OneRow);
}
MyTable.DefaultView.Sort = "Date";
GridView1.DataSource = MyTable;
GridView1.DataBind();
}
现在我们明白了:
现在,我想您可以用一个按钮替换“hyper-link”,也许可以将文件作为字节流读取,然后将其发送给客户端,但上面的内容应该让您从这里开始。
编辑:用户指出他们不想对文件使用 hyper-link(简单 link)。
所以,我们可以这样做:
我们将平面简按钮放入网格中(为什么在您现在声明不想使用 link 时建议、提示、谈论“link”?-我们要为这里的混乱颁奖吗?)。
如果你不想要一个link,那显然我们不需要也不想关心,说说link对吧?????
好的,让我们删除超级 link,然后将平面简按钮放入网格视图中,如下所示:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" CssClass="table">
<Columns>
<asp:BoundField DataField="File Name" HeaderText="File" />
<asp:BoundField DataField="Date" HeaderText="Date" />
<asp:BoundField DataField="File Size" HeaderText="Size" />
<asp:TemplateField HeaderText="Select" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="cmdDownLoad" runat="server" Text="Download" cssclass="btn"
OnClick="cmdDownLoad_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
所以,代码像以前一样加载,现在我们 get/have 这个:
protected void cmdDownLoad_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
string sFileOnly = gRow.Cells[0].Text;
string sFile = Server.MapPath("~/Content/Animals/" + sFileOnly);
string sMineType = MimeMapping.GetMimeMapping(sFile);
byte[] binFile = File.ReadAllBytes(sFile);
Response.ContentType = sMineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + sFileOnly);
Response.BinaryWrite(binFile);
Response.End();
}
所以,我们应该看到这样说:
我已经有很长时间没有使用 WebForms 了,但我不得不更新一个旧网站。我正在尝试制作一个页面,允许用户将文件下载到他们的机器上。我可以获得目录中的文件列表并将其显示在 table 中,但是,我试图将文件名分配给按钮的命令参数,以便我知道名称要在按钮事件中获取的文件。我似乎无法找到从文件夹对象中获取值以填充命令参数的正确方法。没有错误,它只是空白。有什么建议吗?
var listFiles = dir.GetFiles();
<%
foreach(var file in listFiles) { %>
<tr>
<td> </td>
<td><%= file.Name %></td>
<td><%= file.Length %></td>
<td><%= file.CreationTime.ToString("MM/dd/yyyy HH:mm") %></td>
<td>
<asp:LinkButton ID="btnDownload" runat="server"
CommandArgument='<%#Eval("file.Name") %>'
CommandName="DownloadTechFile"
OnCommand="DownloadFile"
ToolTip="Downloaded file">
<span aria-hidden="true" class="fa fa-download"></span>
</asp:LinkButton>
</td>
</tr>
<% } %>
protected void DownloadFile(object sender, CommandEventArgs e)
{
Alert.Hide();
var fileName = e.CommandArgument.ToString();
var fileFullPath = Path.Combine(FileFolderPath, fileName);
if (string.IsNullOrWhiteSpace(fileName) == false)
{
WebClient req = new WebClient();
HttpResponse response = HttpContext.Current.Response;
try
{
response.Clear();
response.ClearContent();
response.ClearHeaders();
response.Buffer = true;
response.AddHeader("Content-Disposition", "attachment;filename=" + fileName);
byte[] data = req.DownloadData(fileFullPath);
//byte[] data = req.DownloadData(Server.MapPath(fileFullPath));
response.BinaryWrite(data);
response.End();
Alert.Show(AlertType.Success, "File downloaded.");
}
catch (Exception ex)
{
logger.Error("Error downloading file from {0}. {1} | {2} | {3}", fileFullPath, ex.Message, ex.StackTrace, ex.InnerException);
Alert.Show(AlertType.Error, string.Format("Error trying to download file: {0}", fileName));
}
}
}
更新: 这是我想到的,以防其他人可以使用它。
<asp:GridView ID="gvFiles" runat="server" AutoGenerateColumns="false" CssClass="table borderless" HeaderStyle-CssClass="fileheader">
<Columns>
<asp:BoundField DataField="FileName" HeaderText="File Name" />
<asp:BoundField DataField="FileSize" HeaderText="File Size" />
<asp:BoundField DataField="Date" HeaderText="Created On" />
<asp:TemplateField HeaderText="">
<ItemTemplate>
<asp:LinkButton ID="btnDownload" runat="server"
CommandArgument='<%# Eval("FileName") %>'
OnClick="DownloadFile"
ToolTip="Downloaded file">
<span aria-hidden="true" class="fa fa-download"></span>
</asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
void LoadGrid()
{
// create a table for the files, populate, and then bind.
DataTable dtFiles = new DataTable();
dtFiles.Columns.Add("Date", typeof(string));
dtFiles.Columns.Add("FileSize", typeof(string));
dtFiles.Columns.Add("FileName", typeof(string));
DirectoryInfo fileDirectory = new DirectoryInfo(FileFolderPath);
foreach (FileInfo file in fileDirectory.GetFiles("*.txt"))
{
DataRow dr = dtFiles.NewRow();
dr["Date"] = file.CreationTime.ToString("MM/dd/yyyy HH:mm");
dr["FileSize"] = Utility.GetBytesReadable(file.Length);
dr["FileName"] = file.Name;
dtFiles.Rows.Add(dr);
}
dtFiles.DefaultView.Sort = "Date DESC";
gvFiles.DataSource = dtFiles;
gvFiles.DataBind();
}
protected void DownloadFile(object sender, EventArgs e)
{
var fileName = (sender as LinkButton).CommandArgument;
var fileFullPath = Path.Combine(FileFolderPath, fileName);
string mineType = MimeMapping.GetMimeMapping(fileFullPath);
if (string.IsNullOrWhiteSpace(fileName) == false)
{
byte[] binFile = File.ReadAllBytes(fileFullPath);
Response.ContentType = mineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + fileName);
Response.BinaryWrite(binFile);
Response.End();
}
}
你可以说使用 gridview,这样说:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" CssClass="table">
<Columns>
<asp:BoundField DataField="File Name" HeaderText="File" />
<asp:BoundField DataField="Date" HeaderText="Date" />
<asp:BoundField DataField="File Size" HeaderText="Size" />
<asp:TemplateField HeaderText="Select" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" CssClass="btn btn-default"
NavigateUrl='<%# Eval("Path") %>' >Down Load</asp:HyperLink>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
后面的代码可以是这样的:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
// create a table for the files
DataTable MyTable = new DataTable();
MyTable.Columns.Add("Date", typeof(string));
MyTable.Columns.Add("File Size", typeof(string));
MyTable.Columns.Add("File Name", typeof(string));
MyTable.Columns.Add("Path", typeof(string));
string strURLFolder = "~/Content/Animals/";
string strFolder = Server.MapPath(strURLFolder);
DirectoryInfo MyDir = new DirectoryInfo(strFolder);
FileInfo[] MyFiles = MyDir.GetFiles("*.*");
foreach (FileInfo MyFile in MyDir.GetFiles("*.*"))
{
DataRow OneRow = MyTable.NewRow();
OneRow["Date"] = MyFile.LastAccessTime;
OneRow["File Size"] = (MyFile.Length / 1024).ToString() + " KB";
OneRow["File Name"] = MyFile.Name;
OneRow["Path"] = strURLFolder + MyFile.Name;
MyTable.Rows.Add(OneRow);
}
MyTable.DefaultView.Sort = "Date";
GridView1.DataSource = MyTable;
GridView1.DataBind();
}
现在我们明白了:
现在,我想您可以用一个按钮替换“hyper-link”,也许可以将文件作为字节流读取,然后将其发送给客户端,但上面的内容应该让您从这里开始。
编辑:用户指出他们不想对文件使用 hyper-link(简单 link)。
所以,我们可以这样做:
我们将平面简按钮放入网格中(为什么在您现在声明不想使用 link 时建议、提示、谈论“link”?-我们要为这里的混乱颁奖吗?)。
如果你不想要一个link,那显然我们不需要也不想关心,说说link对吧?????
好的,让我们删除超级 link,然后将平面简按钮放入网格视图中,如下所示:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="false" CssClass="table">
<Columns>
<asp:BoundField DataField="File Name" HeaderText="File" />
<asp:BoundField DataField="Date" HeaderText="Date" />
<asp:BoundField DataField="File Size" HeaderText="Size" />
<asp:TemplateField HeaderText="Select" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Button ID="cmdDownLoad" runat="server" Text="Download" cssclass="btn"
OnClick="cmdDownLoad_Click" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
所以,代码像以前一样加载,现在我们 get/have 这个:
protected void cmdDownLoad_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
GridViewRow gRow = btn.NamingContainer as GridViewRow;
string sFileOnly = gRow.Cells[0].Text;
string sFile = Server.MapPath("~/Content/Animals/" + sFileOnly);
string sMineType = MimeMapping.GetMimeMapping(sFile);
byte[] binFile = File.ReadAllBytes(sFile);
Response.ContentType = sMineType;
Response.AppendHeader("Content-Disposition", "attachment; filename=" + sFileOnly);
Response.BinaryWrite(binFile);
Response.End();
}
所以,我们应该看到这样说: