SpringBoot使用hutool操作FTP的詳細(xì)過程
項(xiàng)目場(chǎ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 # 端口號(hào) 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對(duì)象
*/
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、測(cè)試
@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ù)亩丝谔?hào)。然后,服務(wù)器使用其20端口(數(shù)據(jù)端口)主動(dòng)連接到客戶端指定的端口進(jìn)行數(shù)據(jù)傳輸。
- 安全性:由于服務(wù)器需要主動(dòng)連接到客戶端的端口,這可能引發(fā)一些安全問題,特別是當(dāng)客戶端位于防火墻或NAT設(shè)備后面時(shí)。
- 適用場(chǎng)景:適用于客戶端位于可以接受入站連接的網(wǎng)絡(luò)環(huán)境,且沒有防火墻或NAT設(shè)備限制的場(chǎng)景。
被動(dòng)模式(Passive Mode):
- 工作原理:客戶端發(fā)送PASV命令給服務(wù)器,服務(wù)器在本地打開一個(gè)端口(通常是高位的非特權(quán)端口),并通過PASV命令的響應(yīng)告訴客戶端這個(gè)端口號(hào)。然后,客戶端主動(dòng)連接到服務(wù)器指定的這個(gè)端口進(jìn)行數(shù)據(jù)傳輸。
- 安全性:由于客戶端主動(dòng)連接到服務(wù)器,這種模式更適合于客戶端位于防火墻或NAT設(shè)備后面的場(chǎng)景,因?yàn)檫@些設(shè)備通常允許出站連接但限制入站連接。
- 適用場(chǎng)景: 特別適用于網(wǎng)絡(luò)環(huán)境不穩(wěn)定、存在防火墻或NAT設(shè)備的場(chǎng)景。
到此這篇關(guān)于SpringBoot使用hutool操作FTP的文章就介紹到這了,更多相關(guān)SpringBoot使用hutool內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot之整合MyBatis實(shí)現(xiàn)CRUD方式
這篇文章主要介紹了SpringBoot之整合MyBatis實(shí)現(xiàn)CRUD方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
java web請(qǐng)求和響應(yīng)中出現(xiàn)中文亂碼問題的解析
這篇文章主要為大家解析了java web請(qǐng)求和響應(yīng)中出現(xiàn)中文亂碼問題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
Java使用Apache compress實(shí)現(xiàn)文件夾壓縮成Zip包
Apache common提供了很多實(shí)用的工具包,這篇文章主要來和大家介紹一下Java如何使用Apache compress包實(shí)現(xiàn)文件夾壓縮成Zip包,希望對(duì)大家有所幫助2024-01-01
SpringBoot整合Redis之編寫RedisConfig
RedisConfig需要對(duì)redis提供的兩個(gè)Template的序列化配置,所以本文為大家詳細(xì)介紹了SpringBoot整合Redis如何編寫RedisConfig,需要的可以參考下2022-06-06
SSH框架網(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-05
SpringBoot 對(duì)象存儲(chǔ) MinIO的詳細(xì)過程
MinIO 是一個(gè)基于 Go 實(shí)現(xiàn)的高性能、兼容 S3 協(xié)議的對(duì)象存儲(chǔ),它適合存儲(chǔ)海量的非結(jié)構(gòu)化的數(shù)據(jù),這篇文章主要介紹了SpringBoot 對(duì)象存儲(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-12
Java項(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

