Как удалить файл после загрузки с помощью ASP.NET MVC?
Я хочу удалить файл сразу после загрузки, как мне это сделать? Я попытался подклассом FilePathResult
и переопределить метод WriteFile
, где я удаляю файл после
HttpResponseBase.TransmitFile
но это зависает приложение.
Можно ли безопасно удалить файл после загрузки пользователем?
Ответы
Ответ 1
Вы можете создать настраиваемый actionfilter для действия с помощью метода OnActionExecuted, который затем удалит файл после завершения действия, что-то вроде
public class DeleteFileAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Delete file
}
}
то ваше действие имеет
[DeleteFileAttribute]
public FileContentResult GetFile(int id)
{
...
}
Ответ 2
Прочитайте в байтах файла, удалите его, вызовите действие Файлового Действия базового контроллера.
public class MyBaseController : Controller
{
protected FileContentResult TemporaryFile(string fileName, string contentType, string fileDownloadName)
{
var bytes = System.IO.File.ReadAllBytes(fileName);
System.IO.File.Delete(fileName);
return File(bytes, contentType, fileDownloadName);
}
}
Кстати, вы можете воздержаться от этого метода, если имеете дело с очень большими файлами, и вы обеспокоены потреблением памяти.
Ответ 3
Создайте файл и сохраните его.
Response.Flush() отправляет все данные клиенту.
Затем вы можете удалить временный файл.
Это работает для меня:
FileInfo newFile = new FileInfo(Server.MapPath(tmpFile));
//create file, and save it
//...
string attachment = string.Format("attachment; filename={0}", fileName);
Response.Clear();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = fileType;
Response.WriteFile(newFile.FullName);
Response.Flush();
newFile.Delete();
Response.End();
Ответ 4
Выше ответы помогли мне, вот что я закончил:
public class DeleteFileAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Flush();
var filePathResult = filterContext.Result as FilePathResult;
if (filePathResult != null)
{
System.IO.File.Delete(filePathResult.FileName);
}
}
}
Ответ 5
Вы можете вернуть только обычный FileStreamResult
, который открывается с помощью FileOptions.DeleteOnClose
. Поток файлов будет удален с помощью asp.net. Этот ответ не требует использования методов ответа низкого уровня, которые могут иметь неприятные последствия в определенных ситуациях. Также никакая дополнительная работа не будет выполнена, как загрузка файла в память целиком.
var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
return File(
fileStream: fs,
contentType: System.Net.Mime.MediaTypeNames.Application.Octet,
fileDownloadName: "File.abc");
Этот ответ основан на ответе Алана Уэста и комментария Тарика Нугрохотомо.
Ответ 6
Я выполнил одно и то же действие в WebAPI. Мне нужно было удалить файл сразу после загрузки сервера формы.
Мы можем создать класс пользовательских ответов. Он принимает путь к файлу как параметр и удаляет его после его передачи.
public class FileHttpResponseMessage : HttpResponseMessage
{
private readonly string filePath;
public FileHttpResponseMessage(string filePath)
{
this.filePath = filePath;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
File.Delete(filePath);
}
}
Используйте этот класс, как показано ниже, и он удалит ваш файл, как только он будет записан в потоке ответов.
var response = new FileHttpResponseMessage(filePath);
response.StatusCode = HttpStatusCode.OK;
response.Content = new StreamContent(new FileStream(filePath, FileMode.Open, FileAccess.Read));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "MyReport.pdf"
};
return response;
Ответ 7
переопределение метода OnResultExecuted, вероятно, является правильным решением. Этот метод запускается после написания ответа.
public class DeleteFileAttribute : ActionFilterAttribute
{
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
filterContext.HttpContext.Response.Flush();
// Delete file
}
}
Код действия:
[DeleteFileAttribute]
public FileContentResult GetFile(int id)
{
//your action code
}
Ответ 8
Попробуйте это. Это будет работать правильно.
public class DeleteFileAttribute : ActionFilterAttribute
{
public override void OnResultExecuted( ResultExecutedContext filterContext )
{
filterContext.HttpContext.Response.Flush();
string filePath = ( filterContext.Result as FilePathResult ).FileName;
File.Delete( filePath );
}
}
Ответ 9
Мой использованный шаблон.
1) Создать файл.
2) Удалите старый созданный файл, FileInfo.CreationTime < DateTime.Now.AddHour(-1)
3) Пользователь загружен.
Как насчет этой идеи?
Ответ 10
РЕШЕНИЕ:
Нужно либо подклассифицировать FileResult, либо создать настраиваемый фильтр действий, но сложная часть - очистить ответ, прежде чем пытаться удалить файл.
Ответ 11
Вот обновленный ответ на основе элегантного решения от @biesiad для ASP.NET MVC (fooobar.com/questions/242538/...)
В основном он возвращает EmptyResult после отправки ответа.
public ActionResult GetFile()
{
string theFilename = "<Full path your file name>"; //Your actual file name
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=<file name to be shown as download>"); //optional if you want forced download
Response.ContentType = "application/octet-stream"; //Appropriate content type based of file type
Response.WriteFile(theFilename); //Write file to response
Response.Flush(); //Flush contents
Response.End(); //Complete the response
System.IO.File.Delete(theFilename); //Delete your local file
return new EmptyResult(); //return empty action result
}
Ответ 12
Я предпочел решение, которое вернул HttpResponseMessage
. Мне понравилась простота ответа Risord, поэтому я создал поток таким же образом. Затем вместо возврата File
я установил свойство HttpResponseMessage.Content
для объекта StreamContent
.
var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
return new HttpResponseMessage()
{
Content = new StreamContent(fs)
};
Ответ 13
Я разместил это решение в fooobar.com/info/242538/...
public ActionResult GetFile()
{
string theFilename = "<Full path your file name>"; //Your actual file name
Response.Clear();
Response.AddHeader("content-disposition", "attachment; filename=<file name to be shown as download>"); //optional if you want forced download
Response.ContentType = "application/octet-stream"; //Appropriate content type based of file type
Response.WriteFile(theFilename); //Write file to response
Response.Flush(); //Flush contents
Response.End(); //Complete the response
System.IO.File.Delete(theFilename); //Delete your local file
return new EmptyResult(); //return empty action result
}