FTP傳送超過2GB大小的檔案時出現System.OverflowException: 數學運算導致溢位,筆記解決方案。
FTP上傳程式碼範例:
public static bool AppendFileOnServer(string fileName, Uri serverUri)
{
// The URI described by serverUri should use the ftp:// scheme.
// It contains the name of the file on the server.
// Example: ftp://contoso.com/someFile.txt.
// The fileName parameter identifies the file containing
// the data to be appended to the file on the server.
if (serverUri.Scheme != Uri.UriSchemeFtp)
{
return false;
}
// Get the object used to communicate with the server.
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
request.Method = WebRequestMethods.Ftp.AppendFile;
StreamReader sourceStream = new StreamReader(fileName);
byte [] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
sourceStream.Close();
request.ContentLength = fileContents.Length;
// This example assumes the FTP site uses anonymous logon.
request.Credentials = new NetworkCredential ("anonymous","janeDoe@contoso.com");
Stream requestStream = request.GetRequestStream();
requestStream.Write(fileContents, 0, fileContents.Length);
requestStream.Close();
FtpWebResponse response = (FtpWebResponse) request.GetResponse();
Console.WriteLine("Append status: {0}",response.StatusDescription);
response.Close();
return true;
}
2GB問題
發生問題點就在requestStream.Write(fileContents, 0, fileContents.Length),原因是傳入Offset及Count變數Int32的最大值只到2,147,483,647
2GB = 2,147,483,648 Byte,所以上傳檔案超過2G就出現System.OverflowException: 數學運算導致溢位。
解決參數型別為Int32問題
解決方式是先預估檔案大小,若超過1GB就拆成100份,依序讀取再依序寫出,這樣每次寫出的檔案大小(fileContents.length)以及起始位置(Offset)就不會超過2G。
byte[] fileContents;
if (FileLength > 1024 * 1024 * 100)
{
Int32 SegFileLength = Convert.ToInt32(FileLength / 100);
using (FileStream sourceStream = new FileStream("來源檔案路徑", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
for (int i = 0; i <= 100; i++)
{
fileContents = new byte[SegFileLength];
Int32 FTPLength = sourceStream.Read(fileContents, 0, Convert.ToInt32(SegFileLength));
requestStream.Write(fileContents, 0, FTPLength);
}
}
}
else
{
using (FileStream sourceStream = new FileStream(mvLocalFullFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
fileContents = new byte[FileLength];
sourceStream.Read(fileContents, 0, Convert.ToInt32(FileLength));
requestStream.Write(fileContents, 0, Convert.ToInt32(FileLength));
}
}
參考:
Stream.Write 方法 (Byte[], Int32, Int32)