使用FTPClient类及Selenium下载FTP文件时,如何保留原始修改/创建日期
如何在FTP下载时保留文件原始修改日期(含Selenium场景)
刚好之前处理过类似的需求,尤其是需要用文件修改日期做校验的场景,确实不能让下载后的文件时间变成脚本运行时间。下面分两种情况给你解决方案:
一、Apache Commons Net FTPClient 实现方案
FTPClient本身没有自动同步远程文件修改时间的功能,但我们可以手动获取远程文件的元数据,然后给本地下载后的文件设置对应时间。具体分两步:
1. 获取远程文件的原始修改时间
使用FTPClient的getModificationTime(String remoteFilePath)方法,它会返回一个类似 YYYYMMDDHHMMSS 格式的字符串(比如20240520143000),我们需要把它转换成Java能识别的时间戳。
2. 给本地文件设置修改时间
下载完成后,用File.setLastModified(long timestamp)方法,把本地文件的最后修改时间改成远程文件的时间。
修改后的完整代码
我把你的代码做了调整,加入了时间同步的逻辑:
package oops; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.TimeZone; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; public class FTPDownloadFileDemo { public static void main(String[] args) { String server = "test.rebex.net"; int port = 21; String user = "demo"; String pass = "password"; FTPClient ftpClient = new FTPClient(); try { ftpClient.connect(server, port); ftpClient.login(user, pass); ftpClient.enterLocalPassiveMode(); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); String remoteFile1 = "/readme.txt"; File downloadFile1 = new File("C:\\project\\readme1.txt"); // 第一步:获取远程文件的修改时间 String remoteModTimeStr = ftpClient.getModificationTime(remoteFile1); // 注意:getModificationTime返回的格式可能带前缀,比如"213 20240520143000",需要截取后面的时间部分 if (remoteModTimeStr != null && remoteModTimeStr.contains(" ")) { remoteModTimeStr = remoteModTimeStr.split(" ")[1]; } // 解析时间字符串为Date(注意FTP时间默认是UTC时区) SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); Date remoteModDate = sdf.parse(remoteModTimeStr); long remoteModTimestamp = remoteModDate.getTime(); // 第二步:下载文件 OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1)); boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1); outputStream1.close(); if (success) { // 第三步:设置本地文件的修改时间 boolean timeSetSuccess = downloadFile1.setLastModified(remoteModTimestamp); if (timeSetSuccess) { System.out.println("File #1 downloaded successfully, and original modification time preserved."); } else { System.out.println("File downloaded, but failed to set modification time."); } } } catch (IOException | ParseException ex) { System.out.println("Error: " + ex.getMessage()); ex.printStackTrace(); } finally { try { if (ftpClient.isConnected()) { ftpClient.logout(); ftpClient.disconnect(); } } catch (IOException ex) { ex.printStackTrace(); } } } }
注意点
- FTP返回的修改时间默认是UTC时区,解析的时候一定要设置时区,否则会有时间偏差。
getModificationTime的返回值可能带有前缀(比如213),需要先截取有效时间部分。
二、结合Selenium的实现方案
Selenium本身是用来操作浏览器的,它并不直接处理FTP下载。这里分两种场景:
场景1:Selenium做前置操作,用FTPClient下载文件
这种情况最常见,比如先通过Selenium登录系统、触发某个生成文件的操作,再用FTPClient去下载文件并同步时间。这时直接复用上面的FTPClient代码即可,把下载逻辑放在Selenium操作之后:
// 先执行Selenium操作 WebDriver driver = new ChromeDriver(); driver.get("https://your-system-url.com"); // 这里做登录、触发文件生成等操作... driver.quit(); // 然后执行FTPClient下载并同步时间(就是上面的代码) FTPClient ftpClient = new FTPClient(); // ... 后续下载和时间同步逻辑 ...
场景2:必须通过浏览器下载FTP文件
如果是通过浏览器访问FTP链接(比如ftp://test.rebex.net/readme.txt)下载文件,浏览器会默认把本地文件的修改时间设为当前时间。这时我们需要:
- 先通过FTPClient获取远程文件的修改时间
- 找到浏览器下载的本地文件
- 给这个文件设置远程文件的修改时间
示例代码片段:
// 第一步:用FTPClient获取远程文件修改时间 FTPClient ftpClient = new FTPClient(); ftpClient.connect("test.rebex.net", 21); ftpClient.login("demo", "password"); String remoteModTimeStr = ftpClient.getModificationTime("/readme.txt"); // 解析时间的逻辑和上面一样... long remoteModTimestamp = ...; ftpClient.disconnect(); // 第二步:用Selenium触发浏览器下载 WebDriver driver = new ChromeDriver(); // 设置浏览器下载路径(避免弹窗) ChromeOptions options = new ChromeOptions(); options.addArguments("--download.default_directory=C:\\project"); driver = new ChromeDriver(options); driver.get("ftp://test.rebex.net/readme.txt"); // 等待下载完成(可以通过检查文件是否存在且大小稳定来判断) Thread.sleep(3000); // 实际项目中建议用显式等待 // 第三步:找到下载的文件并设置修改时间 File downloadedFile = new File("C:\\project\\readme.txt"); downloadedFile.setLastModified(remoteModTimestamp); driver.quit();
注意点
- 浏览器下载的文件名可能和远程文件名一致,但如果有重名会自动加后缀(比如
readme (1).txt),需要处理这种情况。 - 等待下载完成的逻辑要严谨,不能只用
Thread.sleep,可以循环检查文件的大小是否不再变化,或者用WebDriverWait配合文件存在的条件。
内容的提问来源于stack exchange,提问作者Karthik Deepan
相关产品推荐
相关产品推荐

