SpringBoot集成FTP

1.加入核心依赖

复制代码
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.8.0</version>
        </dependency>

完整依赖

复制代码
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.8.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <!-- hutool -->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.22</version>
        </dependency>
    </dependencies>

2.配置文件

复制代码
ftp:
    host: 127.0.0.1
    port: 21
    username: root
    password: root

3.FTP配置类

java 复制代码
package com.example.config;

import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author lenovo
 */
@Configuration
public class FTPConfig {

    @Value("${ftp.host}")
    private String host;

    @Value("${ftp.port}")
    private int port;

    @Value("${ftp.username}")
    private String username;

    @Value("${ftp.password}")
    private String password;

    @Bean
    public FTPClient ftpClient() {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient.connect(host, port);
            ftpClient.login(username, password);
            ftpClient.enterLocalPassiveMode();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ftpClient;
    }
}

4.Service层

java 复制代码
package com.example.service;

import cn.hutool.crypto.digest.MD5;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

@Service
public interface FTPService {


    public boolean uploadFile(MultipartFile file) ;


    public boolean downloadFile(String remoteFilePath, String localFilePath);

    public boolean deleteFile(String remoteFilePath);


}

实现类:

java 复制代码
package com.example.service.impl;

import com.example.service.FTPService;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

@Service
public class FTPServiceImpl implements FTPService {

    @Autowired
    private FTPClient ftpClient;

    @Override
    public boolean uploadFile(MultipartFile file) {
        try {
            String remoteFilePath = "/w/n";
            ftpClient.enterLocalPassiveMode(); // 设置Passive Mode
            ftpClient.setBufferSize(1024 * 1024); // 设置缓冲区大小为1MB
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE); // 设置传输模式为二进制
            createRemoteDirectory(ftpClient, remoteFilePath);
            // 切换工作目录
            boolean success = ftpClient.changeWorkingDirectory(remoteFilePath);
            if (!success) {
                System.out.println("切换工作目录失败:" + remoteFilePath);
                return false;
            }

            if (file.isEmpty()) {
                System.out.println("上传的文件为空");
                return false;
            }

            String s = md5(Objects.requireNonNull(file.getOriginalFilename()));
            success = ftpClient.storeFile(s, file.getInputStream());

            if (success) {
                System.out.println("文件上传成功");
            } else {
                System.out.println("文件上传失败");
            }
            return success;
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件上传失败:" + e.getMessage());
            return false;
        }
    }

    @Override
    public boolean downloadFile(String remoteFilePath, String localFilePath) {
        try {
            boolean b = ftpClient.retrieveFile(remoteFilePath, Files.newOutputStream(Paths.get(localFilePath)));
            System.out.println(b);
            return b;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean deleteFile(String remoteFilePath) {
        try {
            return ftpClient.deleteFile(remoteFilePath);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    // 创建文件夹(多层也可创建) 
    public void createRemoteDirectory(FTPClient ftpClient, String remotePath) throws IOException {
        String[] dirs = remotePath.split("/");
        String tempDir = "";
        for (String dir : dirs) {
            if (dir.isEmpty()) {
                continue;
            }
            tempDir += "/" + dir;
            if (!ftpClient.changeWorkingDirectory(tempDir)) {
                if (!ftpClient.makeDirectory(tempDir)) {
                    throw new IOException("Failed to create remote directory: " + tempDir);
                }
                ftpClient.changeWorkingDirectory(tempDir);
            }
        }
    }

    private static String md5(String fileN) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] digest = md.digest(fileN.getBytes());
            // 将字节数组转换为十六进制字符串
            StringBuilder str = new StringBuilder();
            for (byte b : digest) {
                str.append(String.format("%02x", b));
            }
            fileN = str.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
        return fileN;
    }
}

5.Controller层

java 复制代码
package com.example.controller;

import com.example.service.FTPService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("/ftp")
public class FTPController {

    @Autowired
    private FTPService ftpService;

    @PostMapping("/upload")
    public String uploadFile(MultipartFile file) {
        if (ftpService.uploadFile(file)) {
            return "File uploaded successfully!";
        } else {
            return "Failed to upload file!";
        }
    }

    @GetMapping("/download")
    public String downloadFile(String remoteFilePath, String localFilePath) {
        if (ftpService.downloadFile(remoteFilePath, localFilePath)) {
            return "File downloaded successfully!";
        } else {
            return "Failed to download file!";
        }
    }

    @DeleteMapping("/delete")
    public String deleteFile(@RequestParam String remoteFilePath) {
        if (ftpService.deleteFile(remoteFilePath)) {
            return "File deleted successfully!";
        } else {
            return "Failed to delete file!";
        }
    }
}

6.运行效果

以上就创建好了一个小demo,快去试试吧。

相关推荐
用户31693538118316 分钟前
如何从零编写一个 Spring Boot Starter
spring boot
用户298698530141 小时前
Word 文档字符级格式化:Java 实现方案详解
java·后端
笨鸟飞不快2 小时前
从单个服务到集群:一次完整的性能排查复盘
java·前端
荣码2 小时前
用Streamlit给AI应用套个界面,10行代码出Web页面
java·python
SamDeepThinking2 小时前
Java微服务练习方式
java·后端·微服务
朦胧之12 小时前
AI 编程-老项目改造篇
java·前端·后端
程序猿大帅17 小时前
别再只当调包侠了:用 Spring AI 落地 Function Calling,我被大模型硬生生砸出了三个大坑
java
程序员晓琪18 小时前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端
Flittly18 小时前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
众少成多积小致巨18 小时前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++