linux FTP传输文件无响应

本地Windows开发环境下,FTP传输文件正常,但将服务部署到Linux环境时,会出现无响应的状态。

1 在FTP服务中,涉及到客户端和服务器端的连接,连接就会涉及到端口的打开问题;

2 而端口的打开中,又涉及到主动模式和被动模式。主动模式:客户端开放端口给服务端用;被动模式:服务端开放端口给客户端用。

由于很多客户端在防火墙内,开放端口给服务器端用比较困难。所以用被动模式的时候比较多。

所以在storeFile(),listFiles()时之前需要调用  ftpClient.enterLocalPassiveMode();

这个方法的意思就是每次数据连接之前,ftpClient告诉ftp server开通一个端口来传输数据。

FTP传输文件


import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.MalformedURLException;

@Slf4j
public class FTPUtil {

    //ftp服务器地址
    private static String HOST_NAME = PropertiesUtil.getProperty("ftp.server.ip");

    //ftp服务器端口号默认为21
    private static Integer PORT = Integer.valueOf(PropertiesUtil.getProperty("ftp.port"));

    //ftp登录账号
    private static String USERNAME = PropertiesUtil.getProperty("ftp.user");

    //ftp登录密码
    private static String PASSWORD = PropertiesUtil.getProperty("ftp.pass");

    private static FTPClient ftpClient = null;

    /**
     * 初始化ftp服务器
     */
    private static void initFtpClient() {
        ftpClient = new FTPClient();
        ftpClient.setControlEncoding("utf-8");
        try {
            log.info("connecting...ftp服务器:" + HOST_NAME + ":" + PORT);
            //连接ftp服务器
            ftpClient.connect(HOST_NAME, PORT);
            //登录ftp服务器
            ftpClient.login(USERNAME, PASSWORD);

            ftpClient.sendCommand("OPTS UTF8", "ON");

            //是否成功登录服务器
            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                log.info("connect failed...ftp服务器:" + HOST_NAME + ":" + PORT);
            } else {
                log.info("connect successful...ftp服务器:" + HOST_NAME + ":" + PORT);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     *
     * @param pathname       ftp服务保存地址
     * @param fileName       上传到ftp的文件名
     * @param originfilename 待上传文件的名称(绝对地址) *
     * @return
     */
    public static boolean uploadFile(String pathname, String fileName, String originfilename) {
        boolean flag = false;
        InputStream inputStream = null;
        try {
            log.info("开始上传文件");
            inputStream = new FileInputStream(new File(originfilename));
            initFtpClient();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            CreateDirecroty(pathname);
            ftpClient.makeDirectory(pathname);
            ftpClient.changeWorkingDirectory(pathname);
            ftpClient.enterLocalPassiveMode();
            ftpClient.storeFile(fileName, inputStream);
            inputStream.close();
            ftpClient.logout();
            flag = true;
            log.info("上传文件成功");
        } catch (Exception e) {
            log.info("上传文件失败");
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != inputStream) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return true;
    }

    /**
     * 上传文件
     * @param pathname ftp服务保存地址
     * @param file  文件
     * @param fileName  上传到ftp的文件名
     * @return
     */
    public static boolean uploadFile(String pathname, MultipartFile file, String fileName) {
        boolean flag = false;
        try {
            initFtpClient();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            CreateDirecroty(pathname);
            ftpClient.makeDirectory(pathname);
            ftpClient.changeWorkingDirectory(pathname);
            ftpClient.enterLocalPassiveMode();
            ftpClient.storeFile(fileName, file.getInputStream());
            ftpClient.logout();
            flag = true;
            log.info("上传文件成功");
        } catch (Exception e) {
            log.info("上传文件失败");
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * 下载文件
     *
     * @param pathName
     * @param filename
     * @param out
     * @return
     */
    public static boolean downloadFile(String pathName, String filename, OutputStream out) {
        try {
            log.info("开始下载文件");
            initFtpClient();
            //切换FTP目录
            ftpClient.changeWorkingDirectory(pathName);
            ftpClient.enterLocalPassiveMode();
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (FTPFile file : ftpFiles) {
                if (filename.equalsIgnoreCase(file.getName())) {
                    InputStream inputStream = ftpClient.retrieveFileStream(filename);
                    byte[] buffer = new byte[1024 * 4];
                    int n = 0;
                    while ((n = inputStream.read(buffer)) != -1) {
                        out.write(buffer, 0, n);
                    }
                    out.flush();
                }
            }
            ftpClient.logout();
            log.info("下载文件成功");
            return true;
        } catch (Exception e) {
            log.info("下载文件失败");
            e.printStackTrace();
            return false;
        } finally {
            try {
                out.close();
                if (ftpClient.isConnected()) {
                    ftpClient.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 删除文件 *
     *
     * @param pathname FTP服务器保存目录 *
     * @param filename 要删除的文件名称 *
     * @return
     */
    public static boolean deleteFile(String pathname, String filename) {
        boolean flag = false;
        try {
            log.info("开始删除文件");
            initFtpClient();
            //切换FTP目录
            ftpClient.changeWorkingDirectory(pathname);
            ftpClient.dele(filename);
            ftpClient.logout();
            flag = true;
            log.info("删除文件成功");
        } catch (Exception e) {
            log.info("删除文件失败");
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * 改变目录路径
     */
    public static boolean changeWorkingDirectory(String directory) {
        boolean flag = true;
        try {
            flag = ftpClient.changeWorkingDirectory(directory);
            if (flag) {
                log.info("进入文件夹" + directory + " 成功!");

            } else {
                log.info("进入文件夹" + directory + " 失败!开始创建文件夹");
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return flag;
    }

    /**
     * 创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建
     *
     * @param remote
     * @return
     * @throws IOException
     */
    public static boolean CreateDirecroty(String remote) throws IOException {
        boolean success = true;
        String directory = remote + "/";
        // 如果远程目录不存在,则递归创建远程服务器目录
        if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(new String(directory))) {
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory.indexOf("/", start);
            String path = "";
            String paths = "";
            while (true) {
                String subDirectory = remote.substring(start, end);
                path = path + "/" + subDirectory;
                if (!existFile(path)) {
                    if (makeDirectory(subDirectory)) {
                        changeWorkingDirectory(subDirectory);
                    } else {
                        log.info("创建目录[" + subDirectory + "]失败");
                        changeWorkingDirectory(subDirectory);
                    }
                } else {
                    changeWorkingDirectory(subDirectory);
                }

                paths = paths + "/" + subDirectory;
                start = end + 1;
                end = directory.indexOf("/", start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return success;
    }

    /**
     * 判断ftp服务器文件是否存在
     *
     * @param path
     * @return
     * @throws IOException
     */
    public static boolean existFile(String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }

    /**
     * 创建目录
     */
    public static boolean makeDirectory(String dir) {
        boolean flag = true;
        try {
            flag = ftpClient.makeDirectory(dir);
            if (flag) {
                log.info("创建文件夹" + dir + " 成功!");

            } else {
                log.info("创建文件夹" + dir + " 失败!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

}

此外,保持连接的同时,需要对多个FTP文件进行操作,一定要调用completePendingCommand()释放,否则FTP会断开连接

//操作多文件时候,必须调用completePendingCommand释放,否则FTP会断开连接
ftpClient.completePendingCommand();
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值