日前客戶IT通報有1個大型倉儲檔案(約1GB)FTP上傳2分鐘後就出現連線中斷的訊息:基礎連接已關閉: 接收時發生未預期的錯誤。
其他事證:
- 其他較小的檔案在同一台FTP Server傳送正常。
- 在命令提示字元下(cmd.exe)以FTP指令碼執行可以成功。
筆記這次解決方式:
1.Review FTP上傳程式碼:
public static void Upload(string mvFtpIP, uint mvPort, bool mvUsePassive, bool mvSSL, string mvLogin, string mvPass, string mvFtpPath, string mvLocalFullFileName, string mvRemoteFileName, bool mvKeepAlive)
{
try
{
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(string.Format("ftp://{0}:{1}/{2}{3}"
, mvFtpIP
, mvPort
, mvFtpPath
, mvRemoteFileName));
request.Method = WebRequestMethods.Ftp.UploadFile;
request.KeepAlive = mvKeepAlive;
request.UsePassive = mvUsePassive;
request.Credentials = new NetworkCredential(mvLogin, mvPass);
using (Stream requestStream = request.GetRequestStream())
{
byte[] fileContents;
using (FileStream sourceStream = new FileStream(mvLocalFullFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fileContents = new byte[sourceStream.Length];
sourceStream.Read(fileContents, 0, fileContents.Length);
requestStream.Write(fileContents, 0, fileContents.Length);
}
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
{
response.Close();
Debug.WriteLine("Upload File Complete, status {0}", response.StatusDescription);
}
}
catch (System.Exception se)
{
throw new System.Exception("FTP Upload Error):" + se.Message, se);
}
}
寫出的方式是1次寫入上傳Ftp server的資料流中:
requestStream.Write(fileContents, 0, fileContents.Length);
2.觀察FTP站台的選項: FTP的站台預設控制通道逾時是120秒(2分鐘),感覺嫌疑很大。
但倉儲系統是UNIX系統平台,想申請改人家的設定有困難;試著自己家Try選項,分10次寫出資料流然後觀察流量看看:
for (int i = 0; i < 10; i++)
{
if (i < 9)
{
requestStream.Write(fileContents, fileContents.Length / 10 * i, fileContents.Length / 10);
}
else
{
requestStream.Write(fileContents, fileContents.Length / 10 * i, fileContents.Length - (fileContents.Length / 10 * 9));
}
}
驚!沒想到修改分次寫出資料流後就成功上傳了!
不太明白背後的root cause(抓頭),到底是控制通道還是資料通道逾時?
但感覺分次寫出可以通道保持聯絡(Keep in touch),筆記下來,下次繼續實驗分次次數與傳輸時間的關聯。
後記:
倉儲檔案今天超過2GB,發生了System.OverflowException: 數學運算導致溢位,今晚先寫上次問題的筆記,過年再補今天筆記,來抱女兒玩飛飛去!
參考:
FtpWebRequest.GetRequestStream