У меня есть Действие, которое должно считать файл из безопасного места, таким образом, я должен использовать олицетворение для чтения файла.
Этот код РАБОТЫ:
[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");
}
Единственная проблема с вышеупомянутым кодом состоит в том, что я должен считать весь файл в память, и я собираюсь быть контактом с ОЧЕНЬ большими файлами, таким образом, это не хорошее решение. Но если я заменяю эти 2 строки:
var bytes = System.IO.File.ReadAllBytes(path);
return File(bytes, "application/octet-stream", "FileName");
с этим:
return File(path, "application/octet-stream", "FileName");
Это НЕ работает, и я получаю сообщение об ошибке:
Доступ к пути 'c:\projects\uploads\1\aa2bcbe7-ea99-499d-add8-c1fdac561b0e\Untitled 2.csv' запрещен.
Я предполагаю использование результатов Файла с путем, попытки открыть файл в более позднее время в конвейере запроса, когда я уже "отменил" олицетворение.
Помните, работы кода олицетворения, потому что я могу считать файл в массиве байтов. Что я хочу сделать, хотя поток файл клиенту.
Какая-либо идея, как я могу работать вокруг этого?
Заранее спасибо.
Вы можете попробовать написать собственный 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");