ftp.rename("/A/file.txt", "/B/sub/file.txt") 在多數 FTP 伺服器不支援跨目錄重命名,會回傳 550 錯誤。
boolean moveFile(FTPClient ftp, String srcPath, String destPath) throws IOException {
// 1. 切換到來源目錄(某些伺服器要求)
String srcDir = srcPath.substring(0, srcPath.lastIndexOf('/') + 1);
String srcName = srcPath.substring(srcPath.lastIndexOf('/') + 1);
if (!ftp.changeWorkingDirectory(srcDir)) return false;
// 2. 發送 RNFR (Rename From)
int rnfr = ftp.sendCommand(FTPCmd.RNFR, srcName);
if (rnfr != 350) return false; // 350 Requested file action pending further information
// 3. 發送 RNTO (Rename To) - 使用絕對路徑
int rnto = ftp.sendCommand(FTPCmd.RNTO, destPath);
return rnto == 250; // 250 Requested file action okay, completed
}
private static final String DOWNLOAD_PATH = "/主文件/";
private static final String FTP_ORDER = "/訂單/";
private static final String FTP_TAXBILL = "/發票/";
private static final String FTP_WAYBILL = "/運單/";
private static final String FTP_GOODS = "/貨物/";
public void categorizeFiles(FTPClient ftp, String[] fileNames, String typeCode)
throws IOException {
String targetDir;
switch (typeCode) {
case "0": targetDir = FTP_ORDER; break;
case "1": targetDir = FTP_TAXBILL; break;
case "2": targetDir = FTP_WAYBILL; break;
case "3": targetDir = FTP_GOODS; break;
default: return;
}
for (String fileName : fileNames) {
String baseName = fileName.substring(0, fileName.lastIndexOf('.'));
String src = DOWNLOAD_PATH + baseName + ".xml";
String dest = targetDir + baseName + "2a.xml";
if (moveFile(ftp, src, dest)) {
log.info("移動成功: {} -> {}", src, dest);
} else {
log.error("移動失敗: {}", src);
}
}
}
RNFR/RNTO(RFC 959 標準指令)ftp.makeDirectory(targetDir)ftp.setControlKeepAliveTimeout(300) 防止連線逾時