2011-04-18 68 views
3

我使用ASP.NET
我需要为用户提供用于从服务器下载文件的临时链接。
它应该是一个临时链接(页面),可用于短时间(例如12小时)。我怎样才能生成这个链接(或带链接的临时网页)?创建临时链接供下载

回答

5
http://example.com/download/document.pdf?token=<token> 

<token>部分在这里是关键。如果您不想涉及数据库,请加密链接创建时间,将其转换为URL安全的Base64表示形式,并为用户提供该URL。当它被请求时,解密token并比较存储在那里的日期和当前的日期和时间。

或者,您可以有一个单独的DownloadTokens表,它将将所述token s(可以是GUID)映射到过期日期。

+1

我很喜欢这个想法。我提出的增强它的建议是使用处理程序并加密随时间下载的文档。否则,你将不得不使用httpmodule或其他东西来阻止用户从URL中删除令牌。 – 2011-04-18 13:02:32

+1

@Kevin为什么要加密文件?诚然,你需要一个单独的'IHttpHandler'在这里,但这没什么大不了的。 – 2011-04-18 13:04:08

1

有一百万种方法可以做到这一点。

我曾经为一个项目做过的方式是生成一个唯一的密钥并使用动态下载器脚本来传输文件。当文件请求被创建时,密钥被生成并存储在数据库中,并且创建时间和文件被请求。你建立一个链接到下载脚本并传入密钥。从那里很容易跟踪到期。

1

llya

我会假设你不需要任何的身份验证和安全性是不是一个问题 - 那就是如果有人得到URL他们也将比布尔下载文件。

就我个人而言,我会创建一个HttpHandler,然后创建一些可以附加到URL的唯一字符串。

随后的ProcessRequest空白试验中看到的编码PARAM它是否仍然可行(在您指定的时间框架)如果是这样使用的BinaryWrite呈现文件或如果没有可以使用呈现一定的Response.Write HTML(”过期“)

喜欢的东西:

 
public class TimeHandler : IHttpHandler, IRequiresSessionState 
{ 
    public void ProcessRequest (HttpContext context) 
    { 

     if(this.my_check_has_expired(this.Context.Request.Params["my_token"])) 
     { 
      // Has Expired 

      context.Response.Write("URL Has Expired"); 
      return; 
     } 

     // Render the File 
     Stream stream = new FileStream(File_Name , FileMode.Open); 

     /* read the bytes from the file */ 
     byte[] aBytes = new byte[(int)oStream.Length]; 
     stream.Read(aBytes, 0, (int)oStream.Length); 
     stream.Close(); 

     // Set Headers 
     context.Response.AddHeader("Content-Length", aBytes.Length.ToString()); 
     // ContentType needs to be set also you can force Save As if you require 

     // Send the buffer 
     context.Response.BinaryWrite(aBytes);        

    } 
} 

你需要再安装IIS中的处理程序,但根据版本不同的一点你使用。

+0

严格地说,您不需要IRequireSession状态取决于您是否也在进行某种形式的身份验证或会话跟踪。 – hokapoka 2011-04-18 13:17:56

3

附加一个时间戳的URL,在查询字符串:

page.aspx?time=2011-06-22T22:12 

核对当前时间的时间戳。

为了避免用户改变由他自己的时间戳,也计算了一些秘密哈希过的时间戳,并且还它添加到查询字符串:

page.aspx?time=2011-06-22T22:12&timehash=4503285032 

哈希你可以这样做的所有字段的总和在DateTime中取模某个质数,或时间的字符串表示形式的SHA1总和。现在,用户将无法在不知道正确的散列的情况下更改时间戳。在你的page.aspx中,你检查给定的哈希与时间戳的哈希值。

6

这是一个比较完整的例子。

首先函数使用一个秘密盐加上到期时间来创建一个简短的十六进制字符串:

public static string MakeExpiryHash(DateTime expiry) 
{ 
    const string salt = "some random bytes"; 
    byte[] bytes = Encoding.UTF8.GetBytes(salt + expiry.ToString("s")); 
    using (var sha = System.Security.Cryptography.SHA1.Create()) 
     return string.Concat(sha.ComputeHash(bytes).Select(b => b.ToString("x2"))).Substring(8); 
} 

然后生成与一周到期的链接一个片段:

DateTime expires = DateTime.Now + TimeSpan.FromDays(7); 
string hash = MakeExpiryHash(expires); 
string link = string.Format("http://myhost/Download?exp={0}&k={1}", expires.ToString("s"), hash); 

最后如果给出了有效的链接,则发送文件的下载页面:

DateTime expires = DateTime.Parse(Request.Params["exp"]); 
string hash = MakeExpiryHash(expires); 
if (Request.Params["k"] == hash) 
{ 
    if (expires < DateTime.UtcNow) 
    { 
     // Link has expired 
    } 
    else 
    { 
     string filename = "<Path to file>"; 
     FileInfo fi = new FileInfo(Server.MapPath(filename)); 
     Response.ContentType = "application/octet-stream"; 
     Response.AddHeader("Content-Disposition", "attachment;filename=" + filename); 
     Response.AddHeader("Content-Length", fi.Length.ToString()); 
     Response.WriteFile(fi.FullName); 
     Response.Flush(); 
    } 
} 
else 
{ 
    // Invalid link 
} 

你应该ld肯定会包装在一些异常处理中以捕捉错误的请求。

+0

只需要记住,发送一个日期时间值与秒将导致潜在危险的Request.Path值从客户端(:) :)检测到 – 2016-02-04 00:47:46

+0

Response.WriteFile做了一个好方法?我认为它下载文件在服务器上,然后下载到用户计算机(如果我的文件在其他服务器上) – 2018-03-10 20:09:20