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 服务中遇到异常,因为无法为相同的文件再次初始化文件流。

我想知道是否有办法避免/删除文件锁定,因此在下一次运行时,即使之前的文件流已经锁定了文件,我也可以重新上传同一个文件。

任何帮助将不胜感激,谢谢。

4

1 回答 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

如果您不想走我上面概述的路线(它不会直接回答您的问题),则上述问题的一个简单解决方案是在上传时使用临时文件名,然后在上传完成。无论如何,您确实应该采用这种方法来防止服务器上的应用程序在上传完成之前获取文件。

于 2012-04-25T21:07:53.137 回答