透過 WebMethod 暴露 getFile 方法,接受檔案名稱、偏移量與每次讀取的位元組數(KB 為單位)。核心邏輯如下:
[WebMethod(Description = "<b>大檔案下載</b> 測試")]
public byte[] getFile(string FileName, long Offset, int Count)
{
// 指定下載資料夾與檔名
string strPath = @"E:\" + FileName;
if (Offset < 0) Offset = 0;
byte[] btBuf = new byte[Count];
if (System.IO.File.Exists(strPath))
{
using (System.IO.FileStream fs = new System.IO.FileStream(strPath, System.IO.FileMode.Open))
{
if (Offset < fs.Length)
{
// 若剩餘長度小於請求長度,調整實際讀取長度
if (0 < (fs.Length - Offset) && (fs.Length - Offset) < Count)
{
Count = (int)(fs.Length - Offset);
}
btBuf = new byte[Count];
fs.Seek(Offset, System.IO.SeekOrigin.Begin);
fs.Read(btBuf, 0, Count);
}
else
{
btBuf = null; // 偏移超過檔案長度,回傳 null 表示結束
}
}
}
return btBuf;
}
關鍵點:
FileStream.Seek 定位至指定 Offset。Count 避免讀取超出檔案尾端。using 區塊確保資源正確釋放。客戶端透過迴圈不斷呼叫 getFile,將取得的位元組寫入本地檔案,直到伺服端回傳 null 為止。
private string DownLoadPath(string strClientFilePath, string fileName)
{
string result = "DownLoading...";
ws1.Service s1 = new ws1.Service();
string strPath = strClientFilePath + @"\" + fileName;
string serverFileName = @"Enterprise.msi";
int count = 1024 * 100; // 每次 100 KB
byte[] buffer = new byte[count];
long offset = 0;
int bufferSize = 1;
while (bufferSize > 0)
{
using (System.IO.FileStream ns = new System.IO.FileStream(strPath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite))
{
// 取得本地已寫入長度作為下一次的 Offset
offset = ns.Length;
buffer = s1.getFile(serverFileName, offset, count);
if (buffer != null)
{
ns.Seek(offset, System.IO.SeekOrigin.Begin);
ns.Write(buffer, 0, buffer.Length);
bufferSize = buffer.Length;
}
else
{
bufferSize = -1;
result = "Successful !";
}
}
}
return result;
}
流程說明:
FileMode.OpenOrCreate 開啟本地檔案,若檔案不存在則建立。ns.Length 作為 Offset,實現斷點續傳核心邏輯。null 時結束迴圈,表示下載完成。此範例展示了基於 WebService 的大檔案斷點續傳基本架構。伺服端負責隨機讀取檔案區塊,客戶端負責管理本地寫入位置與迴圈控制。實際生產環境中建議加入: