简介:
续!!!
前一篇介绍将文件上传到ftp服务器和下载以及直接用ftp路径下载的功能。
此篇主要介绍ftp上传下载的另一个工具类,实现步骤一样,未使用ftp连接池,随用随关。
本次实例,内网连接,主动模式!
FTP文件上传和下载:
1.加入依赖,导包(同上篇)
2.在yml配置文件中配置相关信息(同上篇)
3.在config包新建FtpProperties类获取yml配置(同上篇)
4.controller层(同上篇)
5.service层
@Autowired
private FtpProperties ftpProperties;
private FtpUtils client;
//ftp文件上传
public String upload(MultipartFile file) {
if (file == null || file.isEmpty()) {
return null;
}
//获取文件名
String fileName = file.getOriginalFilename();
Objects.requireNonNull(fileName, "the file uploaded is null");
//获取文件后缀
String fileType = getFileType(fileName);
try (FtpUtil client = FtpUtil.getInstance(ftpProperties.getInnerIp(), Integer.parseInt(ftpProperties.getInnerPort()),
ftpProperties.getUserName(), ftpProperties.getPassword())) {
//开启ftp连接
boolean isOpen = client.open();
if (isOpen) {
String date = formatDate("yyyy/MM/", System.currentTimeMillis());
String name = UUID.randomUUID().toString() + fileType;
String filePath = ftpProperties.getFilePath() + date;
//ftp创建目录路径
boolean success = client.mkdirs(filePath);
if (success) {
client.upload(name, filePath, file.getBytes(), true);
} else {
log.error("mkdir is error: {}", "创建路径失败!");
return null;
}
return date + name;
}
} catch (Exception e) {
log.error("upload error" + e.getMessage());
throw new BadRequestException(e.getMessage());
}
//记得关闭连接
if (Objects.nonNull(this.client)) {
this.client.close();
}
return null;
}
public void download(Long id, HttpServletRequest req, HttpServletResponse res){
if (id != null) {
File entity = fileRepository.findById(id).get();
String path = ftpProperties.getFilePath() + entity.getFilePath();
String fileName = entity.getName();
// 重要,需要设置此值,否则下载后打开excel会提示文件需要修复
res.setContentLength(entity.getFileSize());
FtpUtil client = FtpUtil.getInstance(ftpProperties.getInnerIp(), Integer.parseInt(ftpProperties.getInnerPort()),
ftpProperties.getUserName(), ftpProperties.getPassword());
boolean isOpen = client.open();
//判断ftp服务器文件是否存在
boolean containsFile = client.containsFile(ftpPath);
if(!containsFile){
LOG.error("The file {} in ftp is not existed!", ftpPath);
return;
}
if (isOpen) {
try{
String filePath = path.substring(0, path.lastIndexOf("/"));
//根据ftp存储路径自行填写filePath
client.download(filePath, fileName, res.getOutputStream());
} catch (Exception e) {
log.error("download error" + e.getMessage());
throw new BadRequestException(e.getMessage());
}
}
//记得关闭连接
if (Objects.nonNull(this.client)) {
this.client.close();
}
}
}
6.FtpUtil工具类
package cn.com.sealevel.upgrader.common;
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 java.io.*;
import java.net.SocketException;
/**
* FTP工具类
*/
@Slf4j
public class FtpUtils {
private static FtpUtils instance = null;
private static FTPClient ftpClient = null;
private String server;
private int port;
private String username;
private String password;
public FtpUtils(String server, int port, String username, String password) {
super();
this.server = server;
this.port = port;
this.username = username;
this.password = password;
}
public static FtpUtils getInstance(String server, int port, String username, String password) {
if (instance == null) {
instance = new FtpUtils(server, port, username, password);
}
ftpClient = new FTPClient();
return instance;
}
/**
* 连接FTP服务器
*
* @return
*/
private boolean connect() {
boolean stat = false;
try {
if (ftpClient.isConnected()) {
return true;
}
ftpClient.connect(server, port);
stat = true;
} catch (SocketException e) {
stat = false;
log.error(e.getMessage(), e);
} catch (IOException e) {
stat = false;
log.error(e.getMessage(), e);
}
return stat;
}
/**
* 打开FTP服务器
*
* @return
*/
public boolean open() {
if (!connect()) {
return false;
}
try {
// 设置用户名和密码
ftpClient.login(username, password);
// 设置连接超时时间,5000毫秒
ftpClient.setConnectTimeout(500000);
// 设置中文编码集,防止中文乱码
ftpClient.setControlEncoding("GBK");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
// 检测连接是否成功
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
log.error("The password or username is invalid!");
close();
return false;
}
return true;
} catch (IOException e) {
log.error(e.getMessage(), e);
return false;
}
}
/**
* 关闭FTP服务器
*/
public void close() {
try {
if (ftpClient != null && ftpClient.isConnected()) {
ftpClient.logout();
}
} catch (IOException e) {
log.error(e.getMessage(), e);
} finally {
if (ftpClient != null) {
try {
ftpClient.disconnect();
ftpClient = null;
} catch (IOException ioe) {
log.error(ioe.getMessage(), ioe);
}
}
}
}
/**
* 上传文件到FTP服务器
*
* @param filename 文件名
* @param path ftp上文件存储路径
* @param data 文件内容
* @param isActive 主动模式/被动模式
* @return 上传是否成功
*/
public boolean upload(String filename, String path, byte[] data, boolean isActive) {
boolean stat = false;
try (ByteArrayInputStream input = new ByteArrayInputStream(data)) {
ftpClient.changeWorkingDirectory(path);
ftpClient.setBufferSize(1024);
ftpClient.setControlEncoding("GBK");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.setRemoteVerificationEnabled(false);
if (isActive) {
ftpClient.enterLocalActiveMode();
} else {
ftpClient.enterLocalPassiveMode();
}
stat = ftpClient.storeFile(new String(filename.getBytes("utf-8"), "iso-8859-1"), input);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return stat;
}
/**
* 从本地磁盘上传文件到FTP服务器
*
* @param localFile 本地路径
* @param filename 文件名
* @param path ftp上文件存储路径
* @param isActive 主动模式/被动模式
* @return 上传是否成功
*/
public boolean upload(String localFile, String filename, String path, boolean isActive) {
boolean stat = false;
File file = new File(localFile);
try (InputStream in = new FileInputStream(file)) {
ftpClient.changeWorkingDirectory(path);
ftpClient.setBufferSize(1024);
ftpClient.setControlEncoding("GBK");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.setRemoteVerificationEnabled(false);
if (isActive) {
ftpClient.enterLocalActiveMode();
} else {
ftpClient.enterLocalPassiveMode();
}
stat = ftpClient.storeFile(new String(filename.getBytes("utf-8"), "iso-8859-1"), in);
} catch (IOException e) {
log.error(e.getMessage(), e);
}
return stat;
}
/***
* 创建多个层级目录
*
* @param dir
* dong/zzz/ddd/ewv
* @return
*/
public boolean mkdirs(String dir) {
String[] dirs = dir.split("/");
if (dirs.length == 0) {
return false;
}
boolean stat = false;
try {
ftpClient.changeToParentDirectory();
for (String dirss : dirs) {
ftpClient.makeDirectory(dirss);
ftpClient.changeWorkingDirectory(dirss);
}
ftpClient.changeToParentDirectory();
stat = true;
} catch (IOException e) {
stat = false;
log.error(e.getMessage(), e);
}
return stat;
}
/**
* 从FTP服务器下载文件到指定路径localPath
*
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param localPath 下载到本地的位置 格式:H:/download
* @param fileName 文件名称
*/
public void download(String ftpPath, String localPath, String fileName) {
File localFile = new File(localPath + File.separatorChar + fileName);
try (OutputStream os = new FileOutputStream(localFile)) {
//支持中文
ftpClient.setControlEncoding("UTF-8");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalActiveMode();
//ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory(ftpPath);
ftpClient.retrieveFile(new String(fileName.getBytes("utf-8"), "iso-8859-1"), os);
} catch (FileNotFoundException e) {
log.error("没有找到" + ftpPath + "文件");
log.error(e.getMessage(), e);
} catch (SocketException e) {
log.error("连接FTP失败.");
log.error(e.getMessage(), e);
} catch (IOException e) {
log.error("文件读取错误。");
log.error(e.getMessage(), e);
}
}
/**
* 从FTP服务器下载文件到输出流
*
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param fileName 文件名称
* @param outputStream 输出流
*/
public void download(String ftpPath, String fileName, OutputStream outputStream) {
try {
//支持中文
ftpClient.setControlEncoding("UTF-8");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalActiveMode();
ftpClient.changeWorkingDirectory(ftpPath);
ftpClient.retrieveFile(new String(fileName.getBytes("utf-8"), "iso-8859-1"), outputStream);
} catch (FileNotFoundException e) {
log.error("没有找到" + ftpPath + "文件");
log.error(e.getMessage(), e);
} catch (SocketException e) {
log.error("连接FTP失败.");
log.error(e.getMessage(), e);
} catch (IOException e) {
log.error("文件读取错误。");
log.error(e.getMessage(), e);
}
}
/**
* 判断ftp服务器文件是否存在
*
* @param folderPath 需要解析的的文件夹
* @return
*/
public boolean containsFile(String folderPath) {
boolean flag = false;
try {
ftpClient.setControlEncoding("GBK");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.setRemoteVerificationEnabled(false);
ftpClient.enterLocalActiveMode();
//ftpClient.enterLocalPassiveMode();
FTPFile[] ftpFileArr = ftpClient.listFiles(folderPath);
if (ftpFileArr.length > 0) {
flag = true;
}
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return flag;
}
public FTPFile[] listFiles(String directory) {
try {
ftpClient.setControlEncoding("GBK");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalActiveMode();
ftpClient.changeWorkingDirectory(directory);
return ftpClient.listDirectories();
} catch (IOException e) {
log.error("listFiles 文件读取错误。");
}
return new FTPFile[0];
}
}
当FTP上传文件出现这个报错信息:Host attempting data connection 192.168.2.113 is not same as server 10.20.61.140
加上这句代码可以解决:ftpClient.setRemoteVerificationEnabled(false); 这句代码的意思是:取消服务器获取自身Ip地址和提交的host进行匹配,否则当不一致时报出以上异常。
complete!!!