C# 动态设置超链接';s NavigateUrl到文件路径不起作用

C# 动态设置超链接';s NavigateUrl到文件路径不起作用,c#,asp.net,download,C#,Asp.net,Download,我正在尝试将超链接控件的NavigateUrl路径设置为文件,以便用户可以单击链接并下载文件。在我的C#和ASPX代码中,URL显示为正确设置,但单击链接不会导致任何事情发生;右键单击链接并尝试保存链接将尝试保存download.htm 在幕后,我正在temp目录中创建文件,并将其移动到一个可供下载的位置。这部分工作;我把它包括在内以供参考 private string MoveFile(string file_name, string file_path) {

我正在尝试将超链接控件的
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;
    }
下面是我目前设置URL的方式:

        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直接放到浏览器中时,文件将正确下载。那么为什么它不能在超链接上工作呢

我还尝试在静态超链接上设置属性。同样的结果。作为比较:
单击我

修改

我的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();

也许我应该把它移到我的代码隐藏文件中?

终于让它起作用了。我使用了一个相对路径,
/Archive\u to\u download.zip
。我已经为下一个sprint记录了ASHX方法。

最终实现了这一点。我使用了一个相对路径,
/Archive\u to\u download.zip
。我已经为下一个sprint记录了ASHX方法。

警告-前面的代码不安全,不要使用。仅供演示。 因为您正在制作一个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\u file
的值将是服务器上的实际物理路径。如果您盲目地获取该值并使用它从您的文件系统读取文件,黑客可以使用相同的技术从您的服务器下载任何文件,至少在您的应用程序文件夹中

这会更安全一些,根据您的场景可能可以使用

如果决定使用
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();
}
为了能够访问处理程序中的会话,还必须实现

类似这样的内容(完整代码,未经测试):

当然,超链接仅在会话仍处于活动状态时有效。如果需要永远维护超链接,则需要实现完全不同的功能

这更安全,因为令牌不唯一的可能性非常小。另外,因为它只在会话中存储令牌,所以如果另一个用户设法“猜测”令牌或尝试暴力方法,他仍然不会得到任何东西,因为值根本不在他的会话中,而是在其他人的会话中

警告-前面的代码不安全,请勿使用。仅供演示。
 lb.NavigateUrl = "~/Picture/" + files[i].Name;
因为您正在制作一个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\u file
的值将是服务器上的实际物理路径。如果您盲目地获取该值并使用它从您的文件系统读取文件,黑客可以使用相同的技术从您的服务器下载任何文件,至少在您的应用程序文件夹中

这会更安全一些,根据您的场景可能可以使用

如果决定使用
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();
}
为了能够访问处理程序中的会话,还必须实现

类似这样的内容(完整代码,未经测试):

当然,超链接仅在会话仍处于活动状态时有效。如果需要永远维护超链接,则需要实现完全不同的功能


这更安全,因为令牌不唯一的可能性非常小。另外,因为它只在会话中存储令牌,所以如果另一个用户设法“猜测”令牌或尝试暴力方法,他仍然不会得到任何东西,因为值根本不在他的会话中,而是在其他人的会话中

是否确实要为超链接使用
文件://
路径?你知道这只会在本地机器上工作,不会对其他任何人起作用吗?@ChrisSinclair:说得好。请提出更好的建议。(无论如何,下一次sprint将把文件推送到客户端,跳过手动下载的步骤。)您可以创建
download.aspx
页面,并将文件名/ID/something作为查询参数的一部分传入。然后通过电子邮件发送文件。您还可以考虑通过该文件设置和链接文件。(记住实现适当的安全性)我正在按照建议制作一个ASHX处理程序页面。如何在
HttpContext
或查询中传递文件名?通过URL查询GET参数传递文件信息(文件名、路径、ID等)。是否确实要为超链接使用
file://
路径?你知道这只会在本地机器上工作,不会对其他任何人起作用吗?@ChrisSinclair:说得好。请提出更好的建议。(值得一提的是,下一个sprint将把文件推送到客户端,跳过手动下载的步骤
 lb.NavigateUrl = "~/Picture/" + files[i].Name;