如果运行您的应用程序池的用户可以读取文件共享(默认为网络服务),您可以完全删除虚拟目录并创建一个 ASP.NET 应用程序,将文件流式传输到浏览器。如果您使用的是 MVC,它只是返回一个文件结果。这有一个额外的好处,您将能够限制用户下载文件。即您可以要求用户登录或具有某些权限才能下载文件。还要确保您测试路径遍历,您不希望用户输入 ../../filename 来下载他们不允许的文件。
选项 1:ASP.NET MVC
public ActionResult Download(string file)
{
// Check for directory traversal attack
if(file.IndexOf('\\') > -1 || file.IndexOf('/') > -1)
{
return new HttpNotFoundResult();
}
file = System.IO.Path.Combine("\\FILE_SHARE_FOLDER\\", file);
if(!System.IO.File.Exists(file))
{
return new HttpNotFoundResult();
}
return this.File(file, GetMimeType(file));
}
选项 2:网络表单
private void DownloadFile(string file)
{
// Check for directory traversal attack
if(file.IndexOf('\\') > -1 || file.IndexOf('/') > -1)
{
Response.StatusCode = 404;
Response.End();
}
file = System.IO.Path.Combine("\\FILE_SHARE_FOLDER\\", file);
if (!System.IO.File.Exists(file))
{
Response.StatusCode = 404;
Response.End();
}
Response.ContentType = GetMimeType(file);
Response.TransmitFile(file);
}
注意您将需要一种方法来获取 MVC 和 Webforms 的 MIME 类型(来自 KodeSharp 的 MIME 类型方法)
private string GetMimeType(string fileName)
{
string mimeType = "application/unknown";
string ext = System.IO.Path.GetExtension(fileName).ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
mimeType = regKey.GetValue("Content Type").ToString();
return mimeType;
}