Как я могу разблокировать блокировку FileStream?

Я реализую модуль для загрузки файлов в куски с клиентской машины на сервер. На стороне сервера я использую WCF Soap.

Чтобы загрузить файлы в куски, я выполнил этот образец из Microsoft http://msdn.microsoft.com/en-us/library/aa717050.aspx. Я смог заставить его работать в простом сценарии, поэтому он загружает файлы в куски. Этот модуль chunking использует WSDualHttpBinding.

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

В моей службе WCF у меня есть метод, который обрабатывает запись файла со стороны сервера:

public void UploadFile(RemoteFileInfo request)
{
FileInfo fi = new FileInfo(Path.Combine(Utils.StorePath(), request.FileName));

if (!fi.Directory.Exists)
{
    fi.Directory.Create();
}

FileStream file = new FileStream(fi.FullName, FileMode.Create, FileAccess.Write);
int count;
byte[] buffer = new byte[4096];
while ((count = request.FileByteStream.Read(buffer, 0, buffer.Length)) > 0)
{
    file.Write(buffer, 0, count);
    file.Flush();
}
request.FileByteStream.Close();
file.Position = 0;
file.Close();

if (request.FileByteStream != null)
{
    request.FileByteStream.Close();
    request.FileByteStream.Dispose();
}
}

Модуль chunking отправляет куски во время выполнения функции request.FileByteStream.Read(buffer, 0, buffer.Length).

После инициализации filestream файл блокируется (это обычное поведение при инициализации потока для записи), но проблема заключается в том, что я останавливаю процесс загрузки во время процесса отправки/получения, то канал, используемый модулем chunking, не отменяется, поэтому файл остается заблокированным, так как служба WCF все еще ожидает отправки большего количества данных до истечения времени ожидания отправки (тайм-аут составляет 1 час, так как мне нужно загрузить файлы + 2,5 ГБ). При следующей загрузке, если я попытаюсь загрузить тот же файл, я получаю исключение в службе WCF, потому что поток filestream не может быть снова инициализирован для того же файла.

Я хотел бы знать, есть ли способ избежать/удалить блокировку файла, поэтому при следующем запуске я могу повторно загрузить тот же файл, даже если предыдущий файловый поток уже заблокировал файл.

Любая помощь была бы оценена, спасибо.

Ответ 1

Мне лично не нравится такое решение. Поддержание связи не является идеальным.

Используя ваш пример, вы можете быть на полпути через файл 2,5 ГБ, и процесс может быть прерван. Вы попадаете в ситуацию, у которой вы выше. Чтобы усугубить ситуацию, вам необходимо повторно отправить все данные, которые уже были отправлены.

Я бы пошел по пути обработки блоков самостоятельно и добавив их к той же стороне файлового сервера. Вызовите метод WCF, который указывает, что файл запускается, загружает данные в блоки и затем вызывает другой метод, когда загрузка завершена. ЕСЛИ вы уверены, что имена файлов уникальны, тогда вы можете даже выполнить это с помощью одного вызова метода.

Что-то вроде:

ulong StartFile(string filename) // This returns the data already uploaded
void UploadFile(string filename, ulong start, byte[] data)
void EndFile(string filename) // Just as a safety net

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