分享一个Java ftp文件下载的方法

最近遇到一个ftp下载超时的问题,解决方法如下:

 1 /**
 2      * 从 FTP 服务器下载文件并写入输出流
 3      *
 4      * @param ftpUrl FTP 文件的 URL
 5      * @param os     输出流
 6      */
 7     public static void writeBytesFromFTP(String ftpUrl, OutputStream os) throws IOException {
 8         // 解析 FTP URL
 9         URL url = new URL(ftpUrl);
10         String host = url.getHost();
11         String path = url.getPath();
12         int lastSlashIndex = path.lastIndexOf('/');
13         String filename = path.substring(lastSlashIndex + 1);
14         // 默认端口为 21
15         int port = url.getPort() > 0 ? url.getPort() : 21;
16         FTPClient ftp = new FTPClient();
17         ftp.setControlEncoding("UTF-8");
18         // 设置连接超时时间为5秒
19         ftp.setConnectTimeout(5000);
20         // 设置数据传输的超时时间也为30秒
21         ftp.setDataTimeout(Duration.ofSeconds(30));
22         try {
23             // 1.连接服务器 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
24             ftp.connect(host, port);
25             // 2.登录服务器
26             boolean loginSuccess = ftp.login(YmlPropertyUtils.getErpFtpName(), YmlPropertyUtils.getErpFtpPwd());
27             if (!loginSuccess) {
28                 throw new RuntimeException("FTP文件服务器登录失败,请检查用户名和密码!");
29             }
30             // 3.判断连接是否成功
31             int reply = ftp.getReplyCode();
32             // 确定回复代码是否为肯定的完成响应。所有以 2 开头的代码都是肯定的完成响应。FTP 服务器将在命令最终成功完成时发送肯定的完成响应。
33             if (!FTPReply.isPositiveCompletion(reply)) {
34                 throw new RuntimeException("FTP连接失败!");
35             }
36 
37             //4.指定要下载的目录,转移到FTP服务器目录
38             String directory = new File(path).getParent();
39             directory = directory == null ? "" : directory;
40             // 设置控制命令的超时时间
41             ftp.setSoTimeout(5000);
42             boolean b = ftp.changeWorkingDirectory(directory);
43             if (!b) {
44                 throw new RuntimeException("FTP文件服务器切换目录失败,请检查目录是否正确!");
45             }
46             // 5.遍历下载的目录
47             FTPFile[] fs;
48             try {
49                 // 进入本地被动模式,这个东西放在listFiles前面,否则会超时
50                 ftp.enterLocalPassiveMode();
51                 // 此信息是通过 LIST 命令获取的, 故要进入本地被动模式(具体原因查看源码或者了解ftp的下载机制)
52                 fs = ftp.listFiles();
53             } catch (IOException e) {
54                 throw new RuntimeException("列出FTP目录时发生错误", e);
55             }
56             if (fs != null) {
57                 for (FTPFile ff : fs) {
58                     //解决中文乱码问题,两次解码
59                     String fn = new String(ff.getName().getBytes("iso-8859-1"), "utf8");
60                     if (fn.equals(filename)) {
61                         //6.写操作,将其写入到输出流
62                         ftp.retrieveFile(ff.getName(), os);
63                         break;
64                     }
65                 }
66             } else {
67                 throw new RuntimeException("FTP文件服务器没有找到文件,请检查文件名是否正确!");
68             }
69         } catch (Exception e) {
70             throw new RuntimeException("从服务器下载文件过程中发生错误", e);
71         } finally {
72             if (os != null) {
73                 os.flush();
74                 os.close();
75             }
76             // 关闭连接
77             if (ftp.isConnected()) {
78                 try {
79                     ftp.logout();
80                     ftp.disconnect();
81                 } catch (IOException ioe) {
82                     log.error("关闭FTP连接时发生错误", ioe);
83                 }
84             }
85         }
86     }

 

posted @ 2024-09-26 09:20  十一点  阅读(152)  评论(0)    收藏  举报