HTTP 上傳大檔案受限於 IIS 上傳大小限制、逾時設定、無法斷點續傳 等缺陷。FTP 協定成熟穩定,原生支援大檔傳輸與續傳。Indy (Internet Direct) 封裝了阻塞式 Socket 操作,讓開發者以同步程式碼風格處理網路傳輸,避開非同步回呼地獄,是 WinForms/WPF/ASP.NET 伺服端整合 FTP 的首選庫。
| 功能 | 關鍵方法/屬性 | 說明 |
|---|---|---|
| 連線 | Connect(), Host, Username, Password, Port | 支援自動登入與逾時設定 |
| 目錄操作 | ChangeDir(), ChangeDirUp(), List(), RetrieveCurrentDir() | 切換、列舉、取得當前路徑 |
| 下載 | Get(remote, local, overwrite, resume) | 支援串流/檔案、覆寫、斷點續傳 |
| 上傳 | Put(local, remote, append) | 支援串流/檔案、續傳模式 |
| 刪除 | Delete(file), RemoveDir(dir) | 檔案/目錄刪除(目錄需為空) |
| 進度監控 | OnWorkBegin, OnWork, OnWorkEnd | 即時更新進度條、速度、剩餘時間 |
| 狀態通知 | OnStatus, OnDisconnected | 連線狀態變化、斷線偵測 |
IdFTP1.RecvBufferSize = 8192; // 接收緩衝 8KB(預設)
IdFTP1.SendBufferSize = 32768; // 發送緩衝 32KB(預設)
大檔傳輸可適度調大 SendBufferSize(如 64KB-256KB),減少系統呼叫次數,提升吞吐量。
IdFTP1.TransferType = TIdFTPTransferType.ftBinary; // 二進位:圖片、壓縮檔、執行檔、Word/Excel
IdFTP1.TransferType = TIdFTPTransferType.ftASCII; // ASCII:純文字、HTML、XML、原始碼
鐵律:List() 目錄列舉必須用 ftASCII,檔案上傳下載必須用 ftBinary,錯誤模式會導致二進位檔損毀或文字換行符錯誤。
if (!IdFTP1.Connected) {
IdFTP1.Host = "ftp.example.com";
IdFTP1.Username = "user";
IdFTP1.Password = "pass";
IdFTP1.Port = 21;
IdFTP1.Connect(); // 預設 AAutoLogin=true, ATimeout=無限
// 進入目標目錄
IdFTP1.ChangeDir("/upload/images");
}
IdFTP1.TransferType = TIdFTPTransferType.ftASCII; // 必須!
var listing = new StringList();
IdFTP1.List(listing); // 同步阻塞直到完成
foreach (var item in listing) {
Console.WriteLine($"{item.FileName} | {item.Size} | {item.ModifiedDate} | {(item.ItemType == TIdDirItemType.ditDirectory ? "DIR" : "FILE")}");
}
IdFTP1.TransferType = TIdFTPTransferType.ftBinary;
string remoteFile = "large_video.mp4";
string localFile = @"C:\Downloads\large_video.mp4";
long remoteSize = IdFTP1.Size(remoteFile); // 取得遠端檔案大小
bool resume = File.Exists(localFile);
long localSize = resume ? new FileInfo(localFile).Length : 0;
if (resume && localSize < remoteSize) {
// 續傳模式:append=true, resume=true
IdFTP1.Get(remoteFile, localFile, false, true);
} else if (!resume) {
// 全新下載
IdFTP1.Get(remoteFile, localFile, true, false);
} else {
Console.WriteLine("檔案已完整存在");
}
IdFTP1.TransferType = TIdFTPTransferType.ftBinary;
string localFile = @"C:\Data\backup.zip";
string remoteFile = "backup.zip";
bool resume = false; // 檢查遠端是否有部分檔案邏輯...
IdFTP1.Put(localFile, remoteFile, resume); // append=resume
Indy 為阻塞式設計,Get/Put 會凍結呼叫執行緒。在 WinForms/WPF/ASP.NET 中必須放入背景執行緒:
// WinForms 範例:BackgroundWorker 或 Task.Run
Task.Run(() => {
try {
IdFTP1.Get(remote, local, false, true);
// 完成後用 Invoke/BeginInvoke 更新 UI
this.BeginInvoke((Action)(() => lblStatus.Text = "下載完成"));
} catch (Exception ex) {
this.BeginInvoke((Action)(() => MessageBox.Show(ex.Message)));
}
});
Indy 也提供 TIdThreadComponent 簡化執行緒管理,但現代 .NET 建議直接使用 Task/async-await 包裝阻塞呼叫。
Size(),若本地較小 → Get(..., resume: true),FTP 指令 REST 設定續傳位移Put(..., append: true),FTP 指令 APPE 從檔案尾部續寫REST (下載) 與 APPE (上傳) 指令,多數現代 FTP Server (vsftpd, ProFTPD, FileZilla Server, IIS FTP) 均支援| 現象 | 可能原因 | 解決方案 |
|---|---|---|
| 連線逾時 | 防火牆阻擋、Port 錯誤、被動模式問題 | 設定 Passive=true、開啟防火牆 21 + 被動埠範圍 |
| 中文檔名亂碼 | FTP 伺服器編碼不一致 | 設定 IdFTP1.Encoding = Encoding.GetEncoding("utf-8") (Indy 10.6+) |
| 大檔傳輸中斷 | 逾時設定過短、網路不穩 | 調大 ReadTimeout/WriteTimeout、啟用續傳邏輯 |
| List() 回傳空白 | TransferType 錯誤 | 列目錄前強制 ftASCII |
| 權限拒絕 550 | 帳號無寫入/刪除權限 | 檢查 FTP 使用者權限、目錄 ACL |
Indy TIdFTP 提供功能完整、API 直覺的 FTP 客戶端實作。掌握 連線管理、傳輸模式切換、續傳邏輯、多執行緒整合 四大核心,即能建構穩健的大檔案傳輸系統。現代專案建議搭配 Task.Run 非同步化阻塞呼叫,並妥善處理編碼、逾時、防火牆等環境變數。