C# FtpWebRequest.Timeout不工作和FtpWebRequest.GetResponse阻塞
我经常上传一个大文件, 然后,在50毫秒的网络延迟和50%的丢包率下,我在FtpWebRequest.GetRequestStream.Write上收到一个IOException,这会使网络变得更糟 我调用FtpWebRequest.GetResponse.Close并希望重新上载该文件,但被阻止 ftp服务器是filezilla 0.9.53,.net版本是2.0。 我的代码显示如下,最后我为我糟糕的英语感到抱歉C# FtpWebRequest.Timeout不工作和FtpWebRequest.GetResponse阻塞,c#,ftp,ftpwebrequest,C#,Ftp,Ftpwebrequest,我经常上传一个大文件, 然后,在50毫秒的网络延迟和50%的丢包率下,我在FtpWebRequest.GetRequestStream.Write上收到一个IOException,这会使网络变得更糟 我调用FtpWebRequest.GetResponse.Close并希望重新上载该文件,但被阻止 ftp服务器是filezilla 0.9.53,.net版本是2.0。 我的代码显示如下,最后我为我糟糕的英语感到抱歉 public class FtpUploader { public Ft
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;
}
公共类FtpUploader
{
公共FtpUploader(字符串用户名、字符串密码)
{
this.certificate=新的网络凭据(用户名、密码);
}
public void上传文件(字符串srcFile,Uri desUri)
{
int retry=20,iLoop=0;
bool finished=UploadFile(srcFile、desUri、WebRequestMethods.Ftp.UploadFile);
当(!完成)
{
如果(iLoop++>=重试)
{
抛出新异常(string.Format(“上载失败”,srcFile,重试));
}
finished=UploadFile(srcFile、desUri、WebRequestMethods.Ftp.AppendFile);
}
}
私有FtpWebRequest CreateFtpWebRequest(Uri,字符串方法)
{
FtpWebRequest ftpClientRequest=(FtpWebRequest)FtpWebRequest.Create(uri);
ftpClientRequest.Credentials=证书;
ftpClientRequest.KeepAlive=false;
ftpClientRequest.Method=Method;
ftpClientRequest.Timeout=20*1000;
ftpClientRequest.ReadWriteTimeout=5*1000;
返回ftpClientRequest;
}
私有长GetFileSize(Uri)
{
FtpWebRequest ftpClientRequest=CreateFtpWebRequest(uri,WebRequestMethods.Ftp.GetFileSize);
FtpWebResponse响应=(FtpWebResponse)ftpClientRequest.GetResponse();
long size=response.ContentLength;
response.Close();
返回大小;
}
私有bool上传文件(字符串srcFile、Uri desUri、字符串ftpMethod)
{
尝试
{
长偏移=0;
if(ftpMethod==WebRequestMethods.Ftp.AppendFile)
{
offset=GetFileSize(desUri);
}
FtpWebRequest请求=CreateFtpWebRequest(desUri,ftpMethod);
request.ContentOffset=偏移量;
Stream desStream=request.GetRequestStream();
FileStream srcStream=newfilestream(srcFile,FileMode.Open,FileAccess.Read);
尝试
{
WriteToDestination(srcStream、desStream、offset);
}
catch(异常ioEx)//IOException
{
LogErrorMsg(ioEx.Message);
}
WebResponse=request.GetResponse();//阻塞
response.Close();
}
捕获(例外情况除外)
{
LogErrorMsg(例如消息);
返回false;
}
返回true;
}
私有void WriteToDestination(流srcStream、流desStream、长偏移量)
{
srcStream.Seek(offset,SeekOrigin.Begin);
int bufSize=4096;
字节[]缓冲区=新字节[bufSize];
long srcLength=srcStream.Length;
while(偏移量
我不知道为什么GetResponse会在Timeout属性无效时阻塞,但我最终发现我可以使用FtpWebRequest.Abort来尝试释放连接。