代码之家  ›  专栏  ›  技术社区  ›  Emad

asp.net mvc中的模拟

  •  6
  • Emad  · 技术社区  · 16 年前

    我有一个需要从安全位置读取文件的操作,因此必须使用模拟来读取该文件。

    此代码有效:

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult DirectDownload(Guid id)
    {
        if (Impersonator.ImpersonateValidUser())
        {
            try
            {
                var path = "path to file";
                if (!System.IO.File.Exists(path))
                {
                    return View("filenotfound");
                }
    
                var bytes = System.IO.File.ReadAllBytes(path);
                return File(bytes, "application/octet-stream", "FileName");
            }
            catch (Exception e)
            {
                Log.Exception(e);
            }finally
            {
                Impersonator.UndoImpersonation();
            }
        }
        return View("filenotfound");
    }
    

    上面代码的唯一问题是,我必须将整个文件读入内存,并且要处理非常大的文件,所以这不是一个好的解决方案。但如果我换掉这两行:

    var bytes = System.IO.File.ReadAllBytes(path);
    return File(bytes, "application/octet-stream", "FileName");
    

    用这个:

    return File(path, "application/octet-stream", "FileName");
    

    它不起作用,我收到错误消息:

    通路 'C:\项目\Uploads\1\aa2bcbe7-ea99-499d-add8-c1fdac561b0e\untitled 2.csv'被拒绝。

    我想,当我已经“撤消”模拟时,将文件结果与路径一起使用,会尝试稍后在请求管道中打开该文件。

    记住,模拟代码可以工作,因为我可以读取字节数组中的文件。不过,我想做的是将文件流到客户端。

    你知道我该怎么解决这个问题吗?

    提前谢谢。

    2 回复  |  直到 11 年前
        1
  •  4
  •   Darin Dimitrov    16 年前

    你可以试着写一个习惯 FilePathResult :

    public class ImpersonatingFileResult : FilePathResult
    {
        public ImpersonatingFileResult(string fileName, string contentType) 
            : base(fileName, contentType)
        { }
    
        protected override void WriteFile(HttpResponseBase response)
        {
            // TODO : Start impersonation
            response.TransmitFile(FileName);
            // TODO : Rollback impersonation
        }
    }
    

    在控制器中:

    return new ImpersonatingFileResult(path, "application/octet-stream");
    
        2
  •  1
  •   Greg    11 年前

    我喜欢 达林的回答 ,但它跳过模拟逻辑,并在iis 7中引发错误…

    所以,我添加了模拟代码 nuget包simpleimersonation .

    此外,对iis 7进行了一些更改,以防止出现无效句柄错误。

    public class ImpersonatingFileResult : FilePathResult
    {
        public ImpersonatingFileResult(string fileName, string contentType)
            : base(fileName, contentType)
        { }
    
        protected override void WriteFile(HttpResponseBase response)
        {
            using (SimpleImpersonation.Impersonation.LogonUser(domain: "SomeDomain", username: "SomeUser", password: "SomePassword", logonType: SimpleImpersonation.LogonType.NewCredentials))
            {
                response.Clear();
                response.ContentType = base.ContentType;
                response.AddHeader("Content-Disposition", "attachment; filename=" + System.IO.Path.GetFileName(base.FileName));
                response.TransmitFile(FileName);
                response.Flush();
            }
        }
    

    然后从控制器使用它:

            return new ImpersonatingFileResult(someFilePath, "Application/pdf");
    

    上面是用来下载文件的,但是如果要显示它,则需要指定“inline”。

                response.Clear();
                response.ContentType = base.ContentType;
                response.AddHeader("Content-Disposition", "inline; filename=\"" + System.IO.Path.GetFileName(base.FileName) + "\"");
                response.TransmitFile(FileName);
                response.Flush();