我使用FtpWebRequest上传大文件, 然后使用Clumsy使网络在50ms网络滞后和50%丢包率下变得更糟,我在FtpWebRequest.GetRequestStream.Write上收到了IOException。
我调用FtpWebRequest.GetResponse.Close并希望重新上传文件,但它会阻止。
ftp服务器是filezilla 0.9.53,.net版本是2.0。 我的代码显示如下,最后我为我糟糕的英语感到抱歉。
public class FtpUploader
{
public FtpUploader(string username, string password)
{
this.certificate = new NetworkCredential(username, password);
}
public void UploadFile(string srcFile, Uri desUri)
{
int retry = 20, iLoop = 0;
bool finished = UploadFile(srcFile, desUri, WebRequestMethods.Ftp.UploadFile);
while (!finished)
{
if (iLoop++ >= retry)
{
throw new Exception(string.Format("Upload Fail", srcFile, retry));
}
finished = UploadFile(srcFile, desUri, WebRequestMethods.Ftp.AppendFile);
}
}
private FtpWebRequest CreateFtpWebRequest(Uri uri, string method)
{
FtpWebRequest ftpClientRequest = (FtpWebRequest)FtpWebRequest.Create(uri);
ftpClientRequest.Credentials = certificate;
ftpClientRequest.KeepAlive = false;
ftpClientRequest.Method = method;
ftpClientRequest.Timeout = 20 * 1000;
ftpClientRequest.ReadWriteTimeout = 5 * 1000;
return ftpClientRequest;
}
private long GetFileSize(Uri uri)
{
FtpWebRequest ftpClientRequest = CreateFtpWebRequest(uri, WebRequestMethods.Ftp.GetFileSize);
FtpWebResponse response = (FtpWebResponse)ftpClientRequest.GetResponse();
long size = response.ContentLength;
response.Close();
return size;
}
private bool UploadFile(string srcFile, Uri desUri, string ftpMethod)
{
try
{
long offset = 0;
if (ftpMethod == WebRequestMethods.Ftp.AppendFile)
{
offset = GetFileSize(desUri);
}
FtpWebRequest request = CreateFtpWebRequest(desUri, ftpMethod);
request.ContentOffset = offset;
Stream desStream = request.GetRequestStream();
FileStream srcStream = new FileStream(srcFile, FileMode.Open, FileAccess.Read);
try
{
WriteToDestination(srcStream, desStream, offset);
}
catch (Exception ioEx) // IOException
{
LogErrorMsg(ioEx.Message);
}
WebResponse response = request.GetResponse(); // blocking
response.Close();
}
catch (Exception ex)
{
LogErrorMsg(ex.Message);
return false;
}
return true;
}
private void WriteToDestination(Stream srcStream, Stream desStream, long offset)
{
srcStream.Seek(offset, SeekOrigin.Begin);
int bufSize = 4096;
byte[] buffer = new byte[bufSize];
long srcLength = srcStream.Length;
while (offset < srcLength)
{
int bytesRead = srcStream.Read(buffer, 0, bufSize);
desStream.Write(buffer, 0, bytesRead);
offset += bytesRead;
}
}
private void LogErrorMsg(string msg)
{
}
private NetworkCredential certificate;
}