您的位置:首页 > 编程语言 > Java开发

Java实现ftp上传下载功能

2017-10-26 14:04 633 查看

前言

平时开发系统的时候,如果需要上传文档,一般都是通过开发好的基础组件比如网盘来上传保存文件。下载的话,一般也是通过http的方式去下载文件。但是遇到比较大的文件,或者遇到了其他的业务需求,有时候还是需要用到ftp协议去传输文件。毕竟ftp作为专业的传输文件协议,还是有着传输效率高的优点的。

搞一个ftp工具类

上传下载还是应该写一个工具类来实现比较方便。这里我们需要引入一个commons-net-3.6.jar的jar包。可以上Apache的官网下载,也可以从文末我分享的网盘链接下载。

一言不合就上代码吧

整个ftp工具类的代码先贴在这里,其中主要代码都有注释。注释会告诉你每一行代码都是做什么的。

package utils;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.SocketException;

/**
* Created by tinybye on 2017/10/23.
*/
public class FtpClientUtils {
private static Logger logger = Logger.getLogger(FtpClientUtils.class);
/**
* 获取FTPClient对象
* @param ftpHost
*            FTP主机服务器
* @param ftpPassword
*            FTP 登录密码
* @param ftpUserName
*            FTP登录用户名
* @param ftpPort
*            FTP端口 默认为21
* @return
*/
public static FTPClient getFTPClient(String ftpHost, String ftpUserName, String ftpPassword, int ftpPort) {
FTPClient ftpClient = new FTPClient();
try {
ftpClient = new FTPClient();
// 连接FTP服务器
ftpClient.connect(ftpHost, ftpPort);
// 登陆FTP服务器
ftpClient.login(ftpUserName, ftpPassword);
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
logger.info("未连接到FTP,用户名或密码错误。");
ftpClient.disconnect();
} else {
logger.info("FTP连接成功。");
}
} catch (SocketException e) {
e.printStackTrace();
logger.info("FTP的IP地址可能错误,请正确配置。");
} catch (IOException e) {
e.printStackTrace();
logger.info("FTP的端口错误,请正确配置。");
}
return ftpClient;
}

/**
* 从FTP服务器下载文件 demo
* @param ftpHost FTP IP地址
* @param ftpUserName FTP 用户名
* @param ftpPassword FTP用户名密码
* @param ftpPort FTP端口
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/document
* @param localPath 下载到本地的位置 格式:windows:E:/download linux或mac:/Users/tinybye/Downloads
* @param fileName 文件名称
*/
public static void downloadFtpFile(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort, String ftpPath, String localPath,
String fileName) {

FTPClient ftpClient = new FTPClient();
try {
ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
// 设置服务器的编码格式,如果与服务器不一致则会导致中文文件下载失败
ftpClient.setControlEncoding("GBK");
//设置文件类型 为二进制
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//数据连接之前开通端口传输数据
ftpClient.enterLocalPassiveMode();
//切换工作路径
ftpClient.changeWorkingDirectory(ftpPath);
// 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
// 如果不想下载文件,比如直接处理文件流做转存操作,则可以获取文件流,不需要在本地服务器生成文件占用存储空间。但是在使用完文件流后需要关闭并调用completePendingCommand()方法
InputStream fileInputStream = ftpClient.retrieveFileStream((new String(fileName.getBytes("GBK"), "ISO-8859-1")));

//处理文件流start
// 关闭文件流,调用completePendingCommand,否则会导致之后的ftpClient无法继续使用
fileInputStream.close();
ftpClient.completePendingCommand();
//处理文件流end

// 保存到本地start
File localFile = new File( localPath + File.separatorChar + fileName);
OutputStream os = new FileOutputStream(localFile);
// 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
ftpClient.retrieveFile(new String(fileName.getBytes("GBK"), "ISO-8859-1"), os);
os.close();
// 保存到本地end
ftpClient.logout();

} catch (FileNotFoundException e) {
logger.error("没有找到" + ftpPath + "文件");
e.printStackTrace();
} catch (SocketException e) {
logger.error("连接FTP失败.");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
logger.error("文件读取错误。");
e.printStackTrace();
}
}
/**
* 上传文件到FTP服务器 demo
* @param ftpHost FTP IP地址
* @param ftpUserName FTP 用户名
* @param ftpPassword FTP用户名密码
* @param ftpPort FTP端口
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/document
* @param localPath 本地文件的位置 格式:windows:E:/download linux或mac:/Users/tinybye/Downloads
* @param fileName 文件名称
*/
public static void uploadFtpFile(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort, String ftpPath, String localPath,
String fileName) {

FTPClient ftpClient = new FTPClient();
try {
ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
// 设置服务器的编码格式,如果与服务器不一致则会导致中文文件下载失败
ftpClient.setControlEncoding("GBK");
//设置文件类型 为二进制
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//数据连接之前开通端口传输数据
ftpClient.enterLocalPassiveMode();
//切换工作路径
ftpClient.changeWorkingDirectory(ftpPath);
// 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
// 上传文件start
File localFile = new File( localPath + File.separatorChar + fileName);
FileInputStream fileInputStream = new FileInputStream(localFile);
// 需要对中文转码,因为ftp协议中文件名需要ISO-8859-1编码
ftpClient.storeFile(new String(fileName.getBytes("GBK"), "ISO-8859-1"), fileInputStream);
fileInputStream.close();
// 上传文件end
ftpClient.logout();

} catch (FileNotFoundException e) {
logger.error("没有找到" + localPath + "文件");
e.printStackTrace();
} catch (SocketException e) {
logger.error("连接FTP失败.");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
logger.error("文件读取错误。");
e.printStackTrace();
}
}
}


常见问题与注意事项

因为在边查资料边开发的过程中还是遇到了一些问题,感觉都是应该注意的问题。其实注释里都有说,但是在这里总结一下吧。

文件名为中文的问题

因为ftp协议中文件名需要ISO-8859-1编码,所以上传和下载的时候要注意对文件名进行转码。当然,这里要注意的是,你要确定ftp服务器设置的编码是utf-8还是GBK,并使用

ftpClient.setControlEncoding("GBK");


进行设置,然后在后面进行转码。

下载文件流后的操作

在使用

ftpClient.retrieveFileStream();


方法从ftp服务器上获取文件流之后,需要先关闭文件流,然后调用

ftpClient.completePendingCommand();


方法。否则之后的ftpClient操作将会失败。

其他

commons-net-3.6.jar包下载

commons-net-3.6.jar

参考文章

Java代码实现FTP文件下载

使用FPT上传下载文件和解决中文名文件乱码问题

调用FTPClient 的retrieveFileStream(String remote)方法后的处理
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java ftp