[.NET][FTP]傳檔發生System.OverflowException: 數學運算導致溢位

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)

Int32.MaxValue 欄位