Java操作FTP

pom依赖

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.6</version>
</dependency>

FTP配置类

// lombok 注解
@Data
public class FtpConfigDto {
    private String ip;
    private int port;
    private String user;
    private String password;
    private String charset;
    private int connectTimeout;
    private int dataTimeout;
    private int keepAliveTimeout;
    private FTPClient ftpClient;
}

FTP文件上传数据

// lombok 注解
@Data
@AllArgsConstructor
public class FtpFileEntry {
    private String path;
    private File file;
}

FTP工具类

// lombok 注解
@Slf4j
public class FtpUtil {

    public static final String SPLITTER = "/";
    public static final int BUFFER_SIZE = 1024; public static final int INTQUANTUM_SECOND_MILLIS = 1000;

    public static void upload(FtpConfigDto config, String path, File file) {
        List<FtpFileEntry> list = new ArrayList<>();
        list.add(new FtpFileEntry(path, file));
        upload(config, list);
    }

    public static void upload(FtpConfigDto config, String path, MultipartFile multipartFile) {
        try {
            String fileName = multipartFile.getOriginalFilename();
            String prefix = fileName.substring(fileName.lastIndexOf("."));
            File file = File.createTempFile(fileName, prefix);
            multipartFile.transferTo(file);
            upload(config, path, new FileInputStream(file));
        } catch (IOException e) {
            log.info("文件上传错误 " + config.getIp(), e);
            throw new RuntimeException("文件上传错误 " + config.getIp(), e);
        }
    }

    public static void upload(FtpConfigDto config, String path, InputStream inputStream) {
        try {
            connect(config);
            String dir = getDir(path);
            String fileName = getFileName(path);
            changeWorkDir(config.getFtpClient(), dir);
            boolean isSuccess = config.getFtpClient().storeFile(convertFileName(fileName), inputStream);
            if(!isSuccess){
                throw new RuntimeExcepton("创建FTP文件失败 ");
            }
        } catch (IOException e) {
            log.info("文件上传错误 " + config.getIp(), e);
            throw new RuntimeException("文件上传错误 " + config.getIp(), e);
        } finally {
            disConnect(config.getFtpClient());
        }
    }

    public static void upload(FtpConfigDto config, List<FtpFileEntry> list) {
        validateLocalFile(list);
        try {
            connect(config);
            for (FtpFileEntry entry : list) {
                try (InputStream inputStream = new BufferedInputStream(new FileInputStream(entry.getFile()))) {
                    String dir = getDir(entry.getPath());
                    String fileName = getFileName(entry.getPath());
                    changeWorkDir(config.getFtpClient(), dir);
                    boolean isSuccess = config.getFtpClient().storeFile(convertFileName(fileName), inputStream);
                    if(!isSuccess){
                        throw new RuntimeExcepton("创建FTP文件失败 ");
                    }
                }
            }
        } catch (IOException e) {
            log.info("文件上传错误 " + config.getIp(), e);
            throw new RuntimeExcepton("文件上传错误 " + config.getIp(), e);
        } finally {
            disConnect(config.getFtpClient());
        }
    }

    public static InputStream readForFTP(FtpConfigDto config, String path) {
        InputStream in;
        InputStream returnIn = null;
        try {
            connect(config);
            String dir = getDir(path);
            String fileName = getFileName(path);
            changeWorkDir(config.getFtpClient(), dir);
            validateRemoteFileExist(config.getFtpClient(), dir, fileName);
            config.getFtpClient().enterLocalPassiveMode();
            in = config.getFtpClient().retrieveFileStream(convertFileName(path));
            if (in != null) {
                returnIn = cloneInputStream(in);
                in.close();
                config.getFtpClient().completePendingCommand();
            }
        } catch (IOException e) {
            log.info("FTP服务器文件读取错误 " + config.getIp(), e);
            throw new RuntimeExcepton("FTP服务器文件读取错误 " + config.getIp(), e);
        } finally {
            disConnect(config.getFtpClient());
        }
        return returnIn;
    }

    public static void download(FtpConfigDto config, String path, File file) {
        List<FtpFileEntry> list = new ArrayList<>();
        list.add(new FtpFileEntry(path, file));
        download(config, list);
    }

    public static void download(FtpConfigDto config, List<FtpFileEntry> list) {
        try {
            connect(config);
            for (FtpFileEntry entry : list) {
                try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(entry.getFile()))) {
                    String dir = getDir(entry.getPath());
                    String fileName = getFileName(entry.getPath());
                    validateRemoteFileExist(config.getFtpClient(), dir, fileName);
                    boolean isSuccess =
                            config.getFtpClient().retrieveFile(convertFileName(entry.getPath()), outputStream);
                    if(!isSuccess){
                        throw new RuntimeException("FTP下载文件失败");
                    }
                    outputStream.flush();
                }
            }
        } catch (IOException e) {
            log.info("文件下载错误 " + config.getIp(), e);
            throw new RuntimeException("文件下载错误 " + config.getIp(), e);
        } finally {
            disConnect(config.getFtpClient());
        }
    }

    public static void remove(FtpConfigDto config, String path) {
        List<String> list = new ArrayList<>();
        list.add(path);
        remove(config, list);
    }

    public static void remove(FtpConfigDto config, List<String> list) {
        try {
            connect(config);
            for (String path : list) {
                String dir = getDir(path);
                String fileName = getFileName(path);
                validateRemoteFileExist(config.getFtpClient(), dir, fileName);
                boolean isSuccess = config.getFtpClient().deleteFile(convertFileName(path));
                if (!isSuccess) {
                    throw new RuntimeException("FTP文件删除失败");
                }
            }
        } catch (IOException e) {
            log.info("文件删除错误 " + config.getIp(), e);
            throw new RuntimeException("文件删除错误 " + config.getIp(), e);
        } finally {
            disConnect(config.getFtpClient());
        }
    }

    public static void move(FtpConfigDto config, String oldFilePath, String newFilePath) {
        try {
            connect(config);
            validateRemoteFileExist(config.getFtpClient(), getDir(oldFilePath), getFileName(oldFilePath));
            boolean isSuccess = config.getFtpClient().rename(oldFilePath, newFilePath);
            if (!isSuccess) {
                throw new RuntimeException("FTP文件移动失败");
            }
        } catch (IOException e) {
            log.info("文件移动错误" + config.getIp(), e);
            throw new RuntimeException("文件移动错误" + config.getIp(), e);
        } finally {
            disConnect(config.getFtpClient());
        }
    }

    public static void rename(FtpConfigDto config, String path, String oldName, String newName) {
        try {
            connect(config);
            validateRemoteFileExist(config.getFtpClient(), path, oldName);
            changeWorkDir(config.getFtpClient(), path);
            boolean isSuccess = rename(config.getFtpClient(), oldName, newName);
            if (!isSuccess) {
                throw new RuntimeException("FTP文件重命名失败");
            }
        } catch (IOException e) {
            log.info("文件重命名错误" + config.getIp(), e);
            throw new RuntimeException("文件重命名错误" + config.getIp(), e);
        } finally {
            disConnect(config.getFtpClient());
        }
    }

    private static boolean rename(FTPClient ftpClient, String oldName, String newName) throws IOException {
        return ftpClient.rename(oldName, newName);
    }

    private static void connect(FtpConfigDto config) throws IOException {
        FTPClient ftpClient = new FTPClient();
        config.setFtpClient(ftpClient);
        ftpClient.connect(config.getIp(), config.getPort());
        if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            boolean isLogin = ftpClient.login(config.getUser(), config.getPassword());
            if(!isLogin){
                throw new RuntimeException("FTP登陆失败");
            }
            ftpClient.setControlEncoding(config.getCharset());
            if (StandardCharsets.UTF_8.name().equals(config.getCharset())
                    && FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
                ftpClient.setControlEncoding(StandardCharsets.UTF_8.name());
            }
            setConfig(config);
        }
    }

    private static void setConfig(FtpConfigDto config) throws IOException {
        FTPClient ftpClient = config.getFtpClient();
        ftpClient.setBufferSize(BUFFER_SIZE);
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
        ftpClient.setConnectTimeout(config.getConnectTimeout() * INTQUANTUM_SECOND_MILLIS);
        ftpClient.setDataTimeout(config.getDataTimeout() * INTQUANTUM_SECOND_MILLIS);
        ftpClient.setControlKeepAliveTimeout(config.getKeepAliveTimeout() * INTQUANTUM_SECOND_MILLIS);
        // 设置被动模式
        ftpClient.enterLocalPassiveMode();
    }

    private static void disConnect(FTPClient ftpClient) {
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.logout();
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            log.info("关闭FTP连接错误", e);
        }
    }

    private static void changeWorkDirDirect(FTPClient ftpClient, String path) throws IOException {
        boolean isSuccess = ftpClient.changeWorkingDirectory(path);
        if(!isSuccess){
            throw new RuntimeException("工作区跳转失败");
        }   
    }

    private static void changeWorkDir(FTPClient ftpClient, String dir) throws IOException {
        if (ftpClient.changeWorkingDirectory(dir)) {
            return;
        }
        StringBuilder pathTemp = new StringBuilder();
        for (String token : StrUtil.split(dir, SPLITTER)) {
            pathTemp.append(SPLITTER).append(token);
            if (!ftpClient.changeWorkingDirectory(pathTemp.toString())) {
                log.debug("目录名称为:" + token);
                boolean isSuccess = ftpClient.makeDirectory(token);
                if (!isSuccess){
                    throw new RuntimeException("创建FTP目录失败");
                }
                changeWorkDirDirect(ftpClient, pathTemp.toString());
            }
        }
    }

    private static void validateLocalFile(List<FtpFileEntry> list) {
        if(CollectionUtils.isEmpty(list)){
            throw new RuntimeException("FTP本地文件列表为空");
        }
        for (FtpFileEntry ftpUploadEntry : list) {
            FileValidate.validateExist(ftpUploadEntry.getFile());
        }
    }

    private static void validateRemoteFileExist(FTPClient ftpClient, String dir, String fileName) throws IOException {
        if (!isRemoteFileExist(ftpClient, dir, fileName)) {
            throw new RuntimeException("远程文件不存在");
        }
    }

    private static boolean isRemoteFileExist(FTPClient ftpClient, String dir, String fileName) throws IOException {
        FTPFile[] arr = ftpClient.listFiles(dir, new FTPFileFilter() {
            @Override
            public boolean accept(FTPFile ftpFile) {
                return ftpFile.getName().equals(fileName);
            }
        });
        return ArrayUtils.isNotEmpty(arr);
    }

    public static String getDir(String path) {
        int i = path.lastIndexOf(SPLITTER);
        return path.substring(0, i);
    }

    private static String getFileName(String path) {
        int i = path.lastIndexOf(SPLITTER);
        return path.substring(i + 1);
    }

    private static String convertFileName(String fileName) {
        return new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
    }

    private static InputStream cloneInputStream(InputStream input) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            InputStream inputStream;
            byte[] buffer = new byte[BUFFER_SIZE];
            int len;
            while ((len = input.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            inputStream = new ByteArrayInputStream(baos.toByteArray());
            return inputStream;
        } catch (IOException e) {
            log.info("复制inputStream失败", e);
            throw e;
        }
    }
}
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容