Я пишу приложение Asp.Net Core (с RazerPages), которое загружает / скачивает файлы.У меня есть элемент управления, который использует AJAX для загрузки файлов кусками.Файлы загружаются в подкаталог на сервере.Имя подкаталога - это guid, который генерируется при загрузке страницы.
Когда я удаляю файл из моего элемента управления, он отправляет команду на удаление связанного файла на сервере.Проблема заключается в том, что для особенно больших файлов удаление, похоже, занимает много времени, но графический интерфейс не ждет ответа (поэтому он считает, что файл уже был удален).Если я затем снова пытаюсь загрузить тот же файл, я получаю исключение «Отказано в доступе», поскольку файл все еще используется другим запросом ...
Я пытался использовать мьютекс для блокировки подкаталога всякий раз, когдапроисходит IO файла, но по разным причинам разные запросы не используют один и тот же мьютекс.Если я использую статический одноэлементный мьютекс, он работает, но это означает, что за один раз можно загрузить / удалить только один файл для всего сервера.
Как создать мьютекс для подкаталога, с которым я сейчас работаю, и распознать его по нескольким запросам?
public class FileIOService : IFileService
{
public string RootDiectory { get; set; }
public void CreateDirectory(Guid id)
{
// Create the working directory if it doesn't exist
string path = Path.Combine(RootDiectory, id.ToString());
lock (id.ToString())
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
}
public void AppendToFile(Guid id, string fileName, Stream content)
{
try
{
CreateDirectory(id);
string fullPath = Path.Combine(RootDiectory, id.ToString(), fileName);
lock (id.ToString())
{
bool newFile = !File.Exists(fullPath);
using (FileStream stream = new FileStream(fullPath, FileMode.Append, FileAccess.Write, FileShare.ReadWrite))
{
using (content)
{
content.CopyTo(stream);
}
}
}
}
catch (IOException ex)
{
throw;
}
}
public void DeleteFile(Guid id, string fileName)
{
string path = Path.Combine(RootDiectory, id.ToString(), fileName);
lock (id.ToString())
{
if (File.Exists(path))
{
File.Delete(path);
}
string dirPath = Path.Combine(RootDiectory, id.ToString());
DirectoryInfo dir = new DirectoryInfo(dirPath);
if (dir.Exists && !dir.GetFiles().Any())
{
Directory.Delete(dirPath, false);
}
}
}
public void DeleteDirectory(Guid id)
{
string path = Path.Combine(RootDiectory, id.ToString());
lock (id.ToString())
{
if (Directory.Exists(path))
{
Directory.Delete(path, true);
}
}
}
}