Как удалить файл после того, как он был передан в ASP.NET Core - PullRequest
0 голосов
/ 27 февраля 2019

Я хотел бы удалить временный файл после возвращения его из формы действия.Как я могу добиться этого с ASP.NET Core:

public IActionResult Download(long id)
{
    var file = "C:/temp/tempfile.zip";
    var fileName = "file.zip;
    return this.PhysicalFile(file, "application/zip", fileName);
    // I Would like to have File.Delete(file) here !!
}

Файл слишком велик для возврата с использованием потока памяти.

Ответы [ 4 ]

0 голосов
/ 27 февраля 2019

File () или PhysicalFile () возвращают класс FileResult, который просто делегирует обработку службе исполнителя.PhysicalFileResult ExecuteResultAsync вызовы метода:

var executor = context.HttpContext.RequestServices
                 .GetRequiredService<IActionResultExecutor<PhysicalFileResult>>();
return executor.ExecuteAsync(context, this);

Все остальные классы, основанные на FileResult, работают аналогичным образом.

Класс PhysicalFileResultExecutor по существу записывает содержимое файла в поток ответа.

Быстрое и грязное решение состоит в создании собственного класса на основе PhysicalFileResult, который делегируетв PhysicalFileResultExecutor, но удаляет файл после его завершения:

public class TempPhysicalFileResult : PhysicalFileResult
{
    public TempPhysicalFileResult(string fileName, string contentType)
                 : base(fileName, contentType) { }
    public TempPhysicalFileResult(string fileName, MediaTypeHeaderValue contentType)
                 : base(fileName, contentType) { }

    public override async  Task ExecuteResultAsync(ActionContext context)
    {
        await base.ExecuteResultAsync(context);
        File.Delete(FileName);
    }
}

Вместо вызова PhysicalFile() для создания PhysicalFileResult вы можете создать и вернуть TempPhysicalFileResult, например:

return new TempPhysicalFileResult(file, "application/zip"){FileDownloadName=fileName};

Это то же самое, что PhysicalFile () делает:

[NonAction]
public virtual PhysicalFileResult PhysicalFile(
    string physicalPath,
    string contentType,
    string fileDownloadName)
    => new PhysicalFileResult(physicalPath, contentType) { FileDownloadName = fileDownloadName };

Более сложным решением было бы создание собственного исполнителя, который позаботился бы, например, о сжатии, а также очистке файлов., оставляя код действия чистым от кода форматирования результата

0 голосов
/ 27 февраля 2019

Вы можете загрузить содержимое файла.удалить файл и отправить контент в ответ.в MVC вы можете вернуть файл в ответ.проверьте фрагмент ниже

public FileResult Download()
{
    var fileName = $"client-file-name.ext";
    var filepath = $"filepath";
    byte[] fileBytes = System.IO.File.ReadAllBytes(filepath);
    //delete file here
    return File(fileBytes, "application/x-msdownload", fileName);
}
0 голосов
/ 27 февраля 2019

Поскольку файл большой, одним из решений является отправка токена (например, guid) вдоль запроса.Только после завершения загрузки вы хотите удалить файл (в противном случае вы рискуете его потерять).Таким образом, используя этот токен, клиент сделает новый запрос, используя вышеупомянутый токен.Таким образом, вы будете знать, что загрузка прошла успешно, и вы можете приступить к удалению файла.

Я предлагаю использовать словарь для сопоставления токена с файлом.

Удаление по одному запросу кажется плохой практикой из-за того, что вы можете легко потерять файл.

Также вы можете использовать ответ Henk Mollema, чтобы быть уверенным, что все файлы периодически удаляются, еслиэто то, что вы пытаетесь достичь.

0 голосов
/ 27 февраля 2019

Было бы трудно сделать это в том же запросе, поскольку запросы заканчиваются сразу после завершения потоковой передачи.Лучшим вариантом может быть запуск синхронизированной фоновой задачи через размещенную службу , которая периодически удаляет все файлы (например, с временем последней записи> 5 минут назад) из временного каталога.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...