如何解锁 FileStream 的锁定?

10

我正在实现一个模块,从客户端机器向服务器上传文件。在服务器端,我使用WCF Soap服务。

为了分块上传文件,我实施了Microsoft的这个示例http://msdn.microsoft.com/en-us/library/aa717050.aspx。我已经能够在简单的情况下使它工作,因此它确实可以分块上传文件。这个分块模块使用了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();
}
}

在函数request.FileByteStream.Read(buffer, 0, buffer.Length)被使用时,分块模块正在发送数据块。

文件流初始化后,文件会被锁定(这是为写入初始化文件流的正常行为),但我遇到的问题是,当发送/接收过程正在执行时停止上传流程,那么分块模块使用的通道不会被取消,因此文件保持被锁定状态,因为WCF服务仍在等待传输更多数据,直到发送超时(超时时间为1小时,因为我需要上传文件+2.5GB)。下次上传时,如果我尝试上传相同的文件,则会在WCF服务处收到异常,因为无法再次为同一文件初始化文件流。

请问是否有方法可以避免/删除文件锁定,以便在下次运行时,即使先前的文件流已经锁定了该文件,也能重新上传同一文件。

非常感谢任何帮助。


这里有用FileStream.Unlock吗? - Xenon
你可以尝试使用FileStream构造函数,并将SharingMode参数设置为System.IO.FileShare.ReadWrite。 - Yiğit Yener
我已经尝试了FileStream.Unlock,但它无法解决问题,因为该文件是在先前的WCF调用中被先前的进程锁定的。 - Fer
1个回答

1

我个人不喜欢这种解决方案。维护连接并不理想。

以你的例子为例,你可能已经完成了一个2.5GB的文件,但进程可能被中止。你最终会陷入上述情况。更糟糕的是,你需要重新提交所有已经提交的数据。

我会选择自己处理块,并将它们附加到同一文件服务器端。调用一个指示文件开始的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

如果您不想按照我上面概述的方法(它并没有直接回答您的问题),那么解决您上述问题的一个简单方法是在上传过程中使用临时文件名,然后在上传完成后将文件重命名。无论如何,您应该采用这种方法来防止服务器上的应用程序在上传完成之前拾取文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接