我正在尝试将HyperLink控件的NavigateUrl
路径设置为文件,以便用户可以单击该链接并下载该文件。在我的C#和ASPX代码中,URL显示正确设置,但点击链接不会发生任何事情;右键单击链接并尝试保存链接尝试保存download.htm
。
在幕后,我正在temp目录中创建文件并将其移动到可用的位置进行下载。这部分有效;我把它包括在内作为参考。
private string MoveFile(string file_name, string file_path)
{
string tempdir = HttpContext.Current.Server.MapPath( ConfigurationManager.AppSettings["docs_folder"] );
string new_file_name = Path.Combine( tempdir, Path.GetFileName( file_name ) );
try
{
if (File.Exists( new_file_name ))
{
File.Delete( new_file_name );
}
File.Move( file_name, new_file_name );
}
catch (Exception e)
{
string message = e.Message;
}
return new_file_name;
}
以下是我目前设置网址的方式:
string download_file = downloader.DownloadFiles(); //Ultimately returns the path from the MoveFile method
hl_download.NavigateUrl = "file:///" + HttpUtility.UrlPathEncode( download_file ).Replace("\\","//");
hl_download.Visible = true;
我的输出如下:
file:///C://users//codes%20with%20hammer//documents//visual%20studio%202012//Projects//Download%20File//Download%20File//Archive_to_download.zip
当我将此URL直接删除到浏览器中时,该文件会正确下载。那么为什么它不能用于超链接呢?
我也尝试在静态超链接上设置属性。结果相同。为了比较:
<asp:HyperLink ID="HyperLink1" runat="server" Visible="True" NavigateUrl="file:///C:/users/codes%20with%20hammer/documents/visual%20studio%202012/Projects/Download%20File//Download%20File//Archive_to_download.zip">click me</asp:HyperLink>
修
我的ASHX页面在ProcessRequest
中包含以下代码:
context.Response.Clear();
context.Response.ContentType = "application/octet-stream";
context.Response.AddHeader( "Content-Disposition", "attachment; filename=" + Path.GetFileName( download_file ));
context.Response.WriteFile( context.Server.MapPath( download_file ) );
context.Response.End();
也许我应该把它移到我的代码隐藏文件中?
答案 0 :(得分:1)
因为您正在制作HttpHandler(根据评论),所以您可以设置NavigateUrl:
string download_file = downloader.DownloadFiles(); //Ultimately returns the path from the MoveFile method
hl_download.NavigateUrl = "~/Handler.ashx?file="+download_file; //simply append the path
hl_download.Visible = true;
现在,问题是download_file
的值将是服务器上的实际物理路径。如果您盲目地使用该值并使用它来从文件系统中读取文件,黑客可以使用相同的技术从您的服务器下载 ANY 文件,至少在您的应用程序文件夹中。
这有点安全,可以根据您的情况使用
如果您决定使用HttpHandler
选项,则必须创建某种唯一令牌,以便将令牌与磁盘上文件的物理路径相关联。如果这是一个只需要生成一次且在会话期间生成的超链接,您可以执行以下操作:
string token = System.Guid.NewGuid().ToString();
Session[token]=download_file; //put the token in the Session dictionary
hl_download.NavigateUrl = "~/Handler.ashx?file="+token;
hl_download.Visible = true;
现在,您可以在HttpHandler
上执行以下操作:
string file = Session[Request.QueryString["file"]];
if (file!=null)
{
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader(string.Format("Content-Disposition", "attachment; filename={0}",Path.GetFileName(file)));
Response.WriteFile(Server.MapPath(file));
Response.End();
}
为了能够在您的处理程序中访问Session,您还必须实现IReadOnlySessionState
像这样(完整代码,未经测试):
public class Handler : IHttpHandler, IReadOnlySessionState
{
public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext ctx)
{
string file = ctx.Session[Request.QueryString["file"]];
if (file!=null)
{
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader(string.Format("Content-Disposition", "attachment; filename={0}",Path.GetFileName(file)));
Response.WriteFile(Server.MapPath(file));
Response.End();
}
}
}
当然,超链接仅在会话仍处于活动状态时有效。如果您需要永久维护超链接,则需要完全实现这一点。
这更安全,因为令牌不唯一的可能性非常小。另外因为它只在会话中存储令牌,所以如果另一个用户设法“猜测”一个令牌或尝试一种蛮力的方法,他仍然不会得到任何东西,因为该值根本不是在他的会议上,但在别人的。
答案 1 :(得分:0)
终于有了这个工作。我使用了相对路径./Archive_to_download.zip
。我已经为下一个sprint记录了ASHX方法。
答案 2 :(得分:0)
lb.NavigateUrl = "~/Picture/" + files[i].Name;