使用FtpClient进行ftp操作

<dependency>
  <groupId>commons-net</groupId>
  <artifactId>commons-net</artifactId>
  <version>3.6</version>
</dependency>
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-pool2</artifactId>
  <version>2.4.3</version>
</dependency>

下载,上传示例

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.junit.Test;

import java.io.*;
import java.nio.charset.Charset;

/**
 * FTPClient
 * <p>
 *
 * @author Feathers
 * @date 2017-11-29 18:00
 */
public class FTPClientDemo {

    private static final String FTP_HOST = "10.35.10.156";
    private static final Integer FTP_PORT = 21;
    private static final String FTP_USERNAME = "ftptest";
    private static final String FTP_PASSWORD = "ftptest";
    private static final String FTP_REMOTE_ROOT_PATH = "/";

    /**
     * 下载ftp上的文件
     */
    @Test
    public void downFile() {
        // 创建一个ftp客户端
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(FTP_HOST, FTP_PORT);
            //如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
            //登录
            ftp.login(FTP_USERNAME, FTP_PASSWORD);
            // 获取FTP响应代码
            reply = ftp.getReplyCode();
            // 如果响应代码完成响应
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
            }
            //转移到FTP服务器目录
            ftp.changeWorkingDirectory(FTP_REMOTE_ROOT_PATH);
            FTPFile[] fs = ftp.listFiles();
            for (FTPFile ff : fs) {
                if (ff.getName().equals("share.txt")) {
                    File localFile = new File("D:ftppool/local/" + ff.getName());
                    OutputStream is = new FileOutputStream(localFile);
                    ftp.retrieveFile(ff.getName(), is);
                    is.close();
                }
            }
            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
    }

    /**
     * 上传文件
     */
    @Test
    public void uploadFile() {
        FTPClient ftp = new FTPClient();
        try {
            int reply;
            ftp.connect(FTP_HOST, FTP_PORT);//连接FTP服务器
            //如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
            ftp.login(FTP_USERNAME, FTP_PASSWORD);//登录
            ftp.setControlEncoding("GBK");
            reply = ftp.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
            }
            ftp.changeWorkingDirectory("/");
            InputStream in = new FileInputStream("C:/Users/Administrator/Desktop/javamail.txt");

            // 上传文件前,对文件名称进行编码转换
            String filename = "我是新上传的文件.txt";
            filename = new String(filename.getBytes(Charset.defaultCharset()),"UTF-8");
            ftp.storeFile(filename, in);
            in.close();
            ftp.logout();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }

}

【FtpClient】FTPClient中的enterLocalPassiveMode();方法

问题:在项目中使用commons-net-1.4.1.jar,在本地测试环境中,上传文件上传不上去:

/***
* ftp图片上传
*
* @param srcFile文件流
* @param destFileName上传后文件名
* @param destFoldName上传后文件包名
*/
public static void ftpUpload(File srcFile, String fileName, String foldName) {
    FTPClient ftpClient = new FTPClient();
    FileInputStream fis = null;

    try {
        //默认端口号:21
        ftpClient.connect("192.168.1.81");
        ftpClient.login("user", "test");
        fis = new FileInputStream(srcFile);
        // 设置上传目录
        ftpClient.changeWorkingDirectory(foldName);
        ftpClient.setBufferSize(1024);
        ftpClient.setControlEncoding("GBK");
        //二进制
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        ftpClient.storeFile(fileName, fis);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            ftpClient.disconnect();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("关闭FTP连接发生异常!", e);
        }
    }
}

解决方案: 关闭防火墙,果然测试成功

但是,问题又一次出现了,连接测试环境算是正常了,但是连接正式环境还是出问题,图片上传不成功,不报错,但是在ftp服务器上查看图片,

根本没有传上去!

经过一番测试后:

发现,加了 ftpClient.enterLocalPassiveMode(); 这句话后,立马可以上传上去数据了!

/***
* ftp图片上传
*
* @param srcFile文件流
* @param destFileName上传后文件名
* @param destFoldName上传后文件包名
*/
public static void ftpUpload(File srcFile, String fileName, String foldName) {
  FTPClient ftpClient = new FTPClient();
  FileInputStream fis = null;

  try {
    //默认端口号:21
    ftpClient.connect("192.168.1.81");
    ftpClient.login("user", "test");
    fis = new FileInputStream(srcFile);
    // 设置上传目录
    ftpClient.changeWorkingDirectory(foldName);
    //加了这句话
    ftpClient.enterLocalPassiveMode();
    ftpClient.setBufferSize(1024);
    ftpClient.setControlEncoding("GBK");
    //二进制
    ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
    ftpClient.storeFile(fileName, fis);
  } catch (IOException e) {
  	e.printStackTrace();
  } finally {
    try {
    	ftpClient.disconnect();
    } catch (IOException e) {
    	e.printStackTrace();
    	throw new RuntimeException("关闭FTP连接发生异常!", e);
    }
  }
}

调用 FTPClient.enterLocalPassiveMode(); 这个方法的意思就是每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据。为什么要这样做呢,因为ftp server可能每次开启不同的端口来传输数据,但是在linux上,由于安全限制,可能某些端口没有开启,所以就出现阻塞。

最后更新于