Я оптимизирую приложение для интенсивного использования диска, которое генерирует много временных файлов, но мне приходится каждый день чистить папки, потому что у нас ограниченное хранилище. Итак, мне интересно, как лучше всего это сделать. Файлы находятся на сетевом диске, доступ к которому осуществляется через виртуальную папку в IIS, поэтому они выглядят как часть собственных папок сайта.
У меня есть онлайн-редактор PDF, использующий Aspose.PDF для .Net.
При использовании приложения оно генерирует много временных файлов, но отображает представление только тогда, когда все они созданы. Поэтому я создаю временный файл, используя предложение Parallel.For, ограниченное количеством процессоров, доступных на компьютере.
Первоначально это делалось последовательно, и с учетом того, что для каждой страницы это занимает от 1 до 3 секунд в зависимости от качества страницы (ограничение ограничений не может быть оптимизировано), требуется слишком много времени для завершения. Мне удалось распараллелить операцию, но время все еще слишком велико.
С другой стороны, у меня есть процедура, которая удаляет все файлы старше 24 часов (86400 секунд) в нескольких каталогах. Сначала это делалось при каждом запросе пользователя (загрузка страницы), поэтому он выполнялся несколько раз в течение жизненного цикла страницы, каждый раз удаляя только кучу файлов.
Все пулы приложений IIS перерабатываются ежедневно в 00 часов, поэтому сейчас я делаю это с помощью Application_Start, но я боюсь, что это замедлит первый пользовательский запрос, поскольку ему нужно удалить около 45 тысяч файлов (сегодня приложение имеет был использован в течение 7 часов и уже 30 тысяч файлов). Мне интересно, если лучший способ сделать следующее:
-Удалите старые файлы на Session_End (скажем, удалите файлы старше 4 часов)
-Обрать все остальные, если они есть, в Application_End (старше 24 часов).
Кроме того, эти подпрограммы вызываются с помощью асинхронных задач, при условии, что мне не нужно ждать их завершения.
Для удаления я использую System.IO.FileInfo.Delete () в цикле for.
Процесс создания временных файлов
Parallel.For(0, TotalPages, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount }, pageCount =>
{
using (MemoryStream imageStream = new MemoryStream())
{
var po = new PageObject();
var idx = pageCount + 1;
PngDevice p = new PngDevice(); // bajamos un poco la resolución
p.RenderingOptions.UseNewImagingEngine = true;
p.Process(doc.Pages[idx], imageStream); // esta instrucción demora cerca de 1 segundo
//System.Drawing.Image image = System.Drawing.Image.FromStream(imageStream);
//ScaleImage(image, 1138, 760, path_base + fileMask + "-" + idx + ".png", out height, out Aratio);
//image.Dispose();
using (System.Drawing.Image image = System.Drawing.Image.FromStream(imageStream))
{
//this scales the image and writes it to a disc
ScaleImage(image, 1138, 760, path_base + fileMask + "-" + idx + ".png", out height, out Aratio);
}
if (idx == 1) { fields = CheckFields(doc, idx, "image" + fileMask + "-" + idx + ".png", fields, Convert.ToDouble(Aratio)); }
po.pageNumber = idx;
po.pageName = "image" + fileMask + "-" + idx + ".png";
po.Height = height;
po.Ratio = Aratio;
lpages.Add(po);
}
});
Запись файла
protected static void ScaleImage(System.Drawing.Image image, int maxWidth, int maxHeight, string path, out string height, out string Aratio)
{
var ratio = (double)maxWidth / image.Width;
Aratio = ratio.ToString();
var newWidth = (int)(image.Width * ratio);
var newHeight = (int)(image.Height * ratio);
height = newHeight.ToString();
//var newImage = new Bitmap(newWidth, newHeight);
using (var newImage = new Bitmap(newWidth, newHeight))
{
Graphics.FromImage(newImage).DrawImage(image, 0, 0, newWidth, newHeight);
using (var bmp = new Bitmap(newImage))
{
bmp.Save(path, ImageFormat.Png);
}
}
//newImage.Dispose();
}
Процесс очистки (имена переменных на испанском языке)
private static int _segundos = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["PeriodoLimpiezaTemp"].ToString());
public static void LimpiarTemporales(string rutaTemporal = "", string mask = "*", int? segundos = null)
{
int time = segundos ?? _segundos;
System.Threading.Tasks.Task.Run(
() =>
{
rutaTemporal = string.IsNullOrEmpty(rutaTemporal) ? Path.GetTempPath() : rutaTemporal;
var dInfo = new DirectoryInfo(rutaTemporal);
var files = dInfo.GetFiles(mask);
foreach (var file in files)
{
var dif = (DateTime.Now - file.CreationTime);
if (dif.TotalSeconds >= time )
{
try
{ //Intenta el eliminar los temporales. Si no puede sigue de largo.
file.Delete();
}
catch
{
//do nothing. Just in case some file it's been used by another process. I don't care if any file is left here, the next run may delete it.
}
}
};
});
}
Где я хочу использовать его в Global.asax
protected void Session_End()
{
int segundos = 14400;
LimpiarTemporales(segundos);
}
protected void Application_End()
{
LimpiarTemporales();
}
Какой лучший подход для создания временных файлов? (Учитывая, что я должен создать их перед рендерингом ...)
А лучший подход к управлению удалением?
Любое предложение приветствуется