1.ftp和ftps
ftp文件传输协议是应用层协议,用于传输文件信息,linux上需要安装vsftpd才能使用(明文传输)
ftps为FTP协议和数据通道添加了SSL功能,可以对传输信息加密
2.ftp传输文件
引入maven依赖
<!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
代码,此处将传入的文件参数改为MultipartFile类型,方便前端传递文件数据,再转为File对象(建立临时文件,上传完成会删除),如果需要可以自己改为文件路径
package com.wyl.ppa.utils;
import java.io.*;
import java.util.TimeZone;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
public class Ftp {
private FTPClient ftpClient;
private String strIp;
private int intPort;
private String user;
private String password;
private static final Logger logger = LoggerFactory.getLogger(Ftp.class);
* Ftp构造函数
public Ftp(String strIp, int intPort, String user, String Password) {
this.strIp = strIp;
this.intPort = intPort;
this.user = user;
this.password = Password;
this.ftpClient = new FTPClient();
* 判断是否登入成功
public void ftpLogin() {
FTPClientConfig ftpClientConfig = new FTPClientConfig();
ftpClientConfig.setServerTimeZoneId(TimeZone.getDefault().getID());
this.ftpClient.setControlEncoding("GBK");
this.ftpClient.configure(ftpClientConfig);
try {
if (this.intPort > 0) {
this.ftpClient.connect(this.strIp, this.intPort);
} else {
this.ftpClient.connect(this.strIp);
// FTP服务器连接回答
int reply = this.ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
this.ftpClient.disconnect();
System.out.println();
logger.error("登录FTP服务失败!");
return;
this.ftpClient.login(this.user, this.password);
// 设置传输协议
this.ftpClient.enterLocalPassiveMode();
this.ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
logger.info(this.user + "成功登陆FTP服务器");
} catch (Exception e) {
e.printStackTrace();
logger.error(this.user + "登录FTP服务失败!" + e.getMessage());
return;
this.ftpClient.setBufferSize(1024 * 2);
this.ftpClient.setDataTimeout(30 * 1000);
* 退出关闭服务器链接
public void ftpLogOut() {
if (null != this.ftpClient && this.ftpClient.isConnected()) {
try {
boolean reuslt = this.ftpClient.logout();// 退出FTP服务器
if (reuslt) {
logger.info("成功退出服务器");
} catch (IOException e) {
e.printStackTrace();
logger.warn("退出FTP服务器异常!" + e.getMessage());
} finally {
try {
this.ftpClient.disconnect();// 关闭FTP服务器的连接
} catch (IOException e) {
e.printStackTrace();
logger.warn("关闭FTP服务器的连接异常!");
* 上传multipartFile文件
* @param multipartFile 上传的文件
* @param romotUpLoadePath 上传服务器路径 - 应该以/结束
public void uploadMultipartFile(MultipartFile multipartFile, String romotUpLoadePath) {
File localFile = FileUtils.multipartFileToFile(multipartFile);
BufferedInputStream inStream = null;
boolean success;
try {
this.ftpClient.changeWorkingDirectory(romotUpLoadePath);// 改变工作路径
inStream = new BufferedInputStream(new FileInputStream(localFile));
logger.info(localFile.getName() + "开始上传.....");
success = this.ftpClient.storeFile(localFile.getName(), inStream);
if (success) {
logger.info(localFile.getName() + "上传成功");
FileUtils.deleteTempFile(localFile);
} catch (FileNotFoundException e) {
e.printStackTrace();
logger.error(localFile + "未找到");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inStream != null) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
* 上传multipartFile文件
* @param localFile 上传的文件
* @param romotUpLoadePath 上传服务器路径 - 应该以/结束
private void uploadFile(File localFile, String romotUpLoadePath) {
BufferedInputStream inStream = null;
boolean success;
try {
this.ftpClient.changeWorkingDirectory(romotUpLoadePath);// 改变工作路径
inStream = new BufferedInputStream(new FileInputStream(localFile));
logger.info(localFile.getName() + "开始上传.....");
success = this.ftpClient.storeFile(localFile.getName(), inStream);
if (success) {
logger.info(localFile.getName() + "上传成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
logger.error(localFile + "未找到");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inStream != null) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
* 下载文件
* @param remoteFileName 待下载文件名称
* @param localDires 下载到当地那个路径下
* @param remoteDownLoadPath remoteFileName所在的路径
public void downloadFile(String remoteFileName, String localDires,
String remoteDownLoadPath) {
String strFilePath = localDires + remoteFileName;
BufferedOutputStream outStream = null;
boolean success = false;
try {
this.ftpClient.changeWorkingDirectory(remoteDownLoadPath);
outStream = new BufferedOutputStream(new FileOutputStream(
strFilePath));
logger.info(remoteFileName + "开始下载....");
success = this.ftpClient.retrieveFile(remoteFileName, outStream);
if (success) {
logger.info(remoteFileName + "成功下载到" + strFilePath);
return;
} catch (Exception e) {
e.printStackTrace();
logger.error(remoteFileName + "下载失败");
} finally {
if (null != outStream) {
try {
outStream.flush();
outStream.close();
} catch (IOException e) {
e.printStackTrace();
if (!success) {
logger.error(remoteFileName + "下载失败!!!");
* 上传文件夹
* @param localDirectory
* 当地文件夹
* @param remoteDirectoryPath
* Ftp 服务器路径 以目录"/"结束
public void uploadDirectory(String localDirectory,
String remoteDirectoryPath) {
File src = new File(localDirectory);
try {
remoteDirectoryPath = remoteDirectoryPath + src.getName() + "/";
this.ftpClient.makeDirectory(remoteDirectoryPath);
// ftpClient.listDirectories();
} catch (IOException e) {
e.printStackTrace();
logger.info(remoteDirectoryPath + "目录创建失败");
File[] allFile = src.listFiles();
assert allFile != null;
for (File file : allFile) {
if (!file.isDirectory()) {
String srcName = file.getPath();
uploadFile(new File(srcName), remoteDirectoryPath);
for (File file : allFile) {
if (file.isDirectory()) {
// 递归
uploadDirectory(file.getPath(),
remoteDirectoryPath);
* 下载文件夹
* @param localDirectoryPath 本地地址
* @param remoteDirectory 远程文件夹
public void downLoadDirectory(String localDirectoryPath,String remoteDirectory) {
try {
String fileName = new File(remoteDirectory).getName();
localDirectoryPath = localDirectoryPath + fileName + "//";
boolean mkdirs = new File(localDirectoryPath).mkdirs();
if(!mkdirs){
logger.error("创建文件失败!");
return;
FTPFile[] allFile = this.ftpClient.listFiles(remoteDirectory);
for (FTPFile ftpFile : allFile) {
if (!ftpFile.isDirectory()) {
downloadFile(ftpFile.getName(), localDirectoryPath, remoteDirectory);
for (FTPFile ftpFile : allFile) {
if (ftpFile.isDirectory()) {
String strremoteDirectoryPath = remoteDirectory + "/" + ftpFile.getName();
downLoadDirectory(localDirectoryPath, strremoteDirectoryPath);
} catch (IOException e) {
e.printStackTrace();
logger.info("下载文件夹失败");
3.ftps
引入maven依赖<dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
代码中设置了私钥,但是我上传没有用到加密功能,需要的话可以自己下载openssl生成一个私钥和公钥,把把公钥放在服务器上,私钥设置在代码里上传就可以了
package com.wyl.ppa.utils;
import com.jcraft.jsch.*;
import java.io.*;
import java.util.Properties;
* Created by zhenghao on 2018/9/18.
public class SFtp {
private ChannelSftp sftp;
private Session session;
* SFTP 登录用户名
private String username;
* SFTP 登录密码
private String password;
private String privateKey;
* SFTP 服务器地址IP地址
private String host;
* SFTP 端口
private int port;
* 构造基于密码认证的sftp对象
public SFtp(String username, String password, String host, int port) {
this.username = username;
this.password = password;
this.host = host;
this.port = port;
* 构造基于秘钥认证的sftp对象
public SFtp(String username, String host, int port, String privateKey) {
this.username = username;
this.host = host;
this.port = port;
this.privateKey = privateKey;
* 连接sftp服务器
public void login() {
try {
JSch jsch = new JSch();
if (privateKey != null) {
jsch.addIdentity(privateKey);// 设置私钥
session = jsch.getSession(username, host, port);
if (password != null) {
session.setPassword(password);
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
} catch (JSchException e) {
e.printStackTrace();
* 关闭连接 server
public void logout() {
if (sftp != null) {
if (sftp.isConnected()) {
sftp.disconnect();
if (session != null) {
if (session.isConnected()) {
session.disconnect();
* 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
* @param directory 上传到该目录
* @param sftpFileName sftp端文件名
public boolean upload(String directory, String sftpFileName, InputStream input) throws SftpException {
try {
if (directory != null && !"".equals(directory)) {
sftp.cd(directory);
sftp.put(input, sftpFileName); //上传文件
return true;
} catch (SftpException e) {
return false;
//上传文件测试
public static void main(String[] args) throws SftpException, IOException {