最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot使用hutool操作FTP的詳細(xì)過程

 更新時(shí)間:2024年09月25日 09:33:21   作者:濤哥是個(gè)大帥比  
在使用SpringBoot結(jié)合hutool操作FTP時(shí),遇到防火墻導(dǎo)致上傳文件大小為0kb的問題,通過設(shè)置FTP為被動(dòng)模式解決,本文詳細(xì)解析了FTP的主動(dòng)模式和被動(dòng)模式的工作原理、安全性及適用場(chǎng)景,幫助理解FTP的連接方式和解決網(wǎng)絡(luò)限制問題

項(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)文章

  • 解決Java包裝類比較時(shí)遇到的問題

    解決Java包裝類比較時(shí)遇到的問題

    所謂包裝類的作用就是將原始數(shù)據(jù)類型轉(zhuǎn)換成引用數(shù)據(jù)類型,下面這篇文章主要給大家介紹了關(guān)于在Java包裝類比較時(shí)遇到的問題的解決方法,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-09-09
  • Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的示例代碼

    Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的示例代碼

    這篇文章主要介紹了Java實(shí)現(xiàn)滑動(dòng)驗(yàn)證碼的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • java 中平方根(sqrt)算法 的實(shí)例詳解

    java 中平方根(sqrt)算法 的實(shí)例詳解

    這篇文章主要介紹了java 中平方根(sqrt)算法 的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • mybatis學(xué)習(xí)之路mysql批量新增數(shù)據(jù)的方法

    mybatis學(xué)習(xí)之路mysql批量新增數(shù)據(jù)的方法

    這篇文章主要介紹了mybatis學(xué)習(xí)之路mysql批量新增數(shù)據(jù)的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • 帶你了解10道java入門面試題

    帶你了解10道java入門面試題

    面試題相信大家都不陌生,想要一個(gè)好的工作面試題必不可少的,下面和小編一起來學(xué)習(xí)與了解Java當(dāng)中有有些什么面試題吧,希望能給你帶來幫助
    2021-08-08
  • Java 利用binarySearch實(shí)現(xiàn)抽獎(jiǎng)計(jì)算邏輯

    Java 利用binarySearch實(shí)現(xiàn)抽獎(jiǎng)計(jì)算邏輯

    這篇文章主要介紹了Java 利用binarySearch實(shí)現(xiàn)抽獎(jiǎng)計(jì)算邏輯,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下
    2020-12-12
  • 2018版java多線程面試題集合及答案

    2018版java多線程面試題集合及答案

    這篇文章主要為大家詳細(xì)介紹了2018版java多線程面試題集合及答案,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • Java中HashMap的put過程詳解

    Java中HashMap的put過程詳解

    這篇文章主要介紹了Java中HashMap的put過程詳解,HashMap有4個(gè)構(gòu)造器,其他構(gòu)造器如果用戶沒有傳入initialCapacity?和loadFactor這兩個(gè)參數(shù),會(huì)使用默認(rèn)值一般如果new?HashMap()不傳值,需要的朋友可以參考下
    2023-07-07
  • struts2實(shí)現(xiàn)簡(jiǎn)單文件下載功能

    struts2實(shí)現(xiàn)簡(jiǎn)單文件下載功能

    這篇文章主要為大家詳細(xì)介紹了struts2實(shí)現(xiàn)簡(jiǎn)單文件下載功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • JMeter連接Mysql數(shù)據(jù)庫(kù)的實(shí)現(xiàn)步驟

    JMeter連接Mysql數(shù)據(jù)庫(kù)的實(shí)現(xiàn)步驟

    本文主要介紹了JMeter操作Mysql數(shù)據(jù)庫(kù),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12

最新評(píng)論

慈利县| 阿城市| 会东县| 大安市| 新丰县| 哈尔滨市| 凭祥市| 拜泉县| 会理县| 泸定县| 北碚区| 体育| 上犹县| 开阳县| 原阳县| 南丰县| 随州市| 嘉定区| 广昌县| 鲜城| 大埔县| 彝良县| 石泉县| 叙永县| 呼玛县| 阿拉尔市| 六安市| 特克斯县| 治多县| 邵武市| 格尔木市| 郯城县| 穆棱市| 嘉禾县| 兴海县| 伊金霍洛旗| 资中县| 高清| 平阳县| 同心县| 广州市|