Подтвердить что ты не робот

Как удалить файл после загрузки с помощью ASP.NET MVC?

Я хочу удалить файл сразу после загрузки, как мне это сделать? Я попытался подклассом FilePathResult и переопределить метод WriteFile, где я удаляю файл после

HttpResponseBase.TransmitFile

но это зависает приложение.

Можно ли безопасно удалить файл после загрузки пользователем?

4b9b3361

Ответ 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
    }