SpringBoot使用hutool操作FTP的詳細(xì)過程
項(xiàng)目場景:
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.15</version> </dependency>
實(shí)現(xiàn)步驟:
1、引入依賴
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.9.0</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.15</version> </dependency>
2、yml配置
ftp: # 服務(wù)器地址 host: 127.0.0.1 # 端口號 port: 21 # 用戶名 userName: test # 密碼 password: test
3、Config配置類
我這里用的是static修飾的變量,方便工具類調(diào)用。
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; /** * ftp配置 */ @Configuration public class FtpConfig { /** * 服務(wù)器地址 */ private static String host; /** * 端口 */ private static Integer port; /** * 用戶名 */ private static String userName; /** * 密碼 */ private static String password; @Value("${ftp.host}") public void setHost(String host) { FtpConfig.host = host; } public static String getHost() { return host; } @Value("${ftp.port}") public void setPort(Integer port) { FtpConfig.port = port; } public static Integer getPort() { return port; } @Value("${ftp.userName}") public void setUserName(String userName) { FtpConfig.userName = userName; } public static String getUserName() { return userName; } @Value("${ftp.password}") public void setPassword(String password) { FtpConfig.password = password; } public static String getPassword() { return password; } }
4、 FtpUtil工具類
import cn.hutool.core.io.FileUtil; import cn.hutool.extra.ftp.Ftp; import cn.hutool.extra.ftp.FtpMode; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.commons.net.ftp.FTPFile; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; /** * FTP服務(wù)工具類 */ @Slf4j public class FtpUtil { /** * 獲取 FTPClient對象 */ private static Ftp getFTPClient() { try { if(StringUtils.isBlank(FtpConfig.getHost()) || FtpConfig.getPort() == null || StringUtils.isBlank(FtpConfig.getUserName()) || StringUtils.isBlank(FtpConfig.getPassword())) { throw new RuntimeException("ftp配置信息不能為空"); } Ftp ftp = new Ftp(FtpConfig.getHost(),FtpConfig.getPort(),FtpConfig.getUserName(),FtpConfig.getPassword()); //設(shè)置為被動(dòng)模式,防止防火墻攔截 ftp.setMode(FtpMode.Passive); return ftp; } catch (Exception e) { e.printStackTrace(); log.error("獲取ftp客戶端異常",e); throw new RuntimeException("獲取ftp客戶端異常:"+e.getMessage()); } } /** * 下載ftp服務(wù)器上的文件到本地 * @param remoteFile ftp上的文件路徑 * @param localFile 輸出的目錄,使用服務(wù)端的文件名 */ public static void download(String remoteFile, String localPath) { if(StringUtils.isBlank(remoteFile) || StringUtils.isBlank(localPath)) { return; } Ftp ftp = getFTPClient(); try { if(!FileUtil.exist(localPath)){ FileUtil.mkdir(localPath); } File lFile = FileUtil.file(localPath); ftp.download(remoteFile, lFile); } catch (Exception e) { e.printStackTrace(); log.error("FTP文件下載異常",e); } finally { //關(guān)閉連接 try { if(ftp != null) ftp.close(); } catch (IOException e) { throw new RuntimeException(e); } } } /** * 本地文件上傳到ftp服務(wù)器上 * @param remoteDir 上傳的ftp目錄 * @param remoteFileName 保存到ftp服務(wù)器上的名稱 * @param localFile 本地文件全名稱 */ public static boolean upload(String remoteDir, String remoteFileName, String localFile) { if(StringUtils.isBlank(remoteDir) || StringUtils.isBlank(remoteFileName) || StringUtils.isBlank(localFile)) { return false; } Ftp ftp = getFTPClient(); try { File lFile = FileUtil.file(localFile); if(!lFile.exists()) { log.error("本地文件不存在"); return false; } if(StringUtils.isBlank(remoteFileName)) { return ftp.upload(remoteDir, lFile); } else { return ftp.upload(remoteDir, remoteFileName, lFile); } } catch (Exception e) { e.printStackTrace(); log.error("文件上傳FTP異常",e); return false; } finally { //關(guān)閉連接 try { if(ftp != null) ftp.close(); } catch (IOException e) { throw new RuntimeException(e); } } } /** * 刪除FTP服務(wù)器中的文件 * @param remoteFile ftp上的文件路徑 */ public static boolean delFile(String remoteFile) { if(StringUtils.isBlank(remoteFile)) { return false; } Ftp ftp = getFTPClient(); try { return ftp.delFile(remoteFile); } catch (Exception e) { e.printStackTrace(); log.error("刪除FTP服務(wù)器中的文件異常",e); return false; } finally { //關(guān)閉連接 try { if(ftp != null) ftp.close(); } catch (IOException e) { throw new RuntimeException(e); } } } /** * 遍歷某個(gè)目錄下所有文件,不會(huì)遞歸遍歷 * @param path 目錄 */ public static List<String> listFile(String path) { List<String> listFile = new ArrayList<>(); Ftp ftp = getFTPClient(); try { FTPFile[] ftpFiles = ftp.lsFiles(path); for (int i = 0; i < ftpFiles.length; i++) { FTPFile ftpFile = ftpFiles[i]; if(ftpFile.isFile()){ listFile.add(ftpFile.getName()); } } return listFile; } catch (Exception e) { e.printStackTrace(); log.error("遍歷某個(gè)目錄下所有文件異常",e); return null; } finally { //關(guān)閉連接 try { if(ftp != null) ftp.close(); } catch (IOException e) { throw new RuntimeException(e); } } } }
5、測試
@RestController @RequestMapping("/test") public class TestController { @RequestMapping(value = "ftpTest", method = RequestMethod.GET) public void ftpTest() { //上傳文件到ftp FtpUtil.upload("opt/upload","APP_RELATION.sql", "F:/APP_RELATION.sql"); //下載遠(yuǎn)程文件 FtpUtil.download("opt/upload/APP_RELATION.sql", "D:/"); //刪除遠(yuǎn)程文件 FtpUtil.delFile("opt/upload/APP_RELATION.sql"); } }
總結(jié):
上傳的時(shí)候碰到一個(gè)問題,就是本地開啟防火墻時(shí),上傳的文件大小是0kb,必須要關(guān)了防火墻才正常,后來FTP模式設(shè)置為“被動(dòng)模式”解決。
//設(shè)置為被動(dòng)模式,防止防火墻攔截 ftp.setMode(FtpMode.Passive);
主動(dòng)模式(Active Mode):
- 工作原理:客戶端在本地打開一個(gè)非特權(quán)端口(通常大于1023),并通過這個(gè)端口發(fā)送PORT命令給服務(wù)器,告訴服務(wù)器客戶端用于數(shù)據(jù)傳輸?shù)亩丝谔?。然后,服?wù)器使用其20端口(數(shù)據(jù)端口)主動(dòng)連接到客戶端指定的端口進(jìn)行數(shù)據(jù)傳輸。
- 安全性:由于服務(wù)器需要主動(dòng)連接到客戶端的端口,這可能引發(fā)一些安全問題,特別是當(dāng)客戶端位于防火墻或NAT設(shè)備后面時(shí)。
- 適用場景:適用于客戶端位于可以接受入站連接的網(wǎng)絡(luò)環(huán)境,且沒有防火墻或NAT設(shè)備限制的場景。
被動(dòng)模式(Passive Mode):
- 工作原理:客戶端發(fā)送PASV命令給服務(wù)器,服務(wù)器在本地打開一個(gè)端口(通常是高位的非特權(quán)端口),并通過PASV命令的響應(yīng)告訴客戶端這個(gè)端口號。然后,客戶端主動(dòng)連接到服務(wù)器指定的這個(gè)端口進(jìn)行數(shù)據(jù)傳輸。
- 安全性:由于客戶端主動(dòng)連接到服務(wù)器,這種模式更適合于客戶端位于防火墻或NAT設(shè)備后面的場景,因?yàn)檫@些設(shè)備通常允許出站連接但限制入站連接。
- 適用場景: 特別適用于網(wǎng)絡(luò)環(huán)境不穩(wěn)定、存在防火墻或NAT設(shè)備的場景。
到此這篇關(guān)于SpringBoot使用hutool操作FTP的文章就介紹到這了,更多相關(guān)SpringBoot使用hutool內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot之整合MyBatis實(shí)現(xiàn)CRUD方式
這篇文章主要介紹了SpringBoot之整合MyBatis實(shí)現(xiàn)CRUD方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08java web請求和響應(yīng)中出現(xiàn)中文亂碼問題的解析
這篇文章主要為大家解析了java web請求和響應(yīng)中出現(xiàn)中文亂碼問題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10Java使用Apache compress實(shí)現(xiàn)文件夾壓縮成Zip包
Apache common提供了很多實(shí)用的工具包,這篇文章主要來和大家介紹一下Java如何使用Apache compress包實(shí)現(xiàn)文件夾壓縮成Zip包,希望對大家有所幫助2024-01-01SpringBoot整合Redis之編寫RedisConfig
RedisConfig需要對redis提供的兩個(gè)Template的序列化配置,所以本文為大家詳細(xì)介紹了SpringBoot整合Redis如何編寫RedisConfig,需要的可以參考下2022-06-06SSH框架網(wǎng)上商城項(xiàng)目第6戰(zhàn)之基于DataGrid的數(shù)據(jù)顯示
SSH框架網(wǎng)上商城項(xiàng)目第6戰(zhàn)之基于DataGrid的數(shù)據(jù)顯示,提供了豐富的選擇、排序、分組和編輯數(shù)據(jù)的功能支持,感興趣的小伙伴們可以參考一下2016-05-05SpringBoot 對象存儲(chǔ) MinIO的詳細(xì)過程
MinIO 是一個(gè)基于 Go 實(shí)現(xiàn)的高性能、兼容 S3 協(xié)議的對象存儲(chǔ),它適合存儲(chǔ)海量的非結(jié)構(gòu)化的數(shù)據(jù),這篇文章主要介紹了SpringBoot 對象存儲(chǔ) MinIO,需要的朋友可以參考下2023-07-07淺談基于Token的WEB后臺(tái)認(rèn)證機(jī)制
這篇文章主要介紹了淺談基于Token的WEB后臺(tái)認(rèn)證機(jī)制,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12Java項(xiàng)目中如何引入Hutool工具類并正確使用它
Hutool是一個(gè)小而全的Java工具類庫,通過靜態(tài)方法封裝,降低相關(guān)API的學(xué)習(xí)成本,提高工作效率,使Java擁有函數(shù)式語言般的優(yōu)雅,這篇文章主要給大家介紹了關(guān)于Java項(xiàng)目中如何引入Hutool工具類并正確使用它的相關(guān)資料,需要的朋友可以參考下2024-01-01