之前写的博客是做一个简单的ftp工具类,但是简单的上传下载已经实现了,由于比较简单便改进了,之前是在util和Controller里调用就完事了,后面改进为在utils,service和controller里都走一遍,但是还是有问题,比如它下载时无论ftp有没有这个文件都会显示下载成功,有的话下载原文件,没有的话它会自动创建一个空的文本下载,比较头疼,后面改进了,引用了别人的代码,我就贴一下改进后的代码:
改进后的完整Utils类:
@Component
public class FTPUtils {
private static final Logger logger = LoggerFactory.getLogger(FTPUtils.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();
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
ftpClient.login(ftpUserName, ftpPassword);// 登陆FTP服务器
if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
System.out.println("未连接到FTP,用户名或密码错误。");
ftpClient.disconnect();
} else {
System.out.println("FTP连接成功。");
}
} catch (SocketException e) {
e.printStackTrace();
System.out.println("FTP的IP地址可能错误,请正确配置。");
} catch (IOException e) {
e.printStackTrace();
System.out.println("FTP的端口错误,请正确配置。");
}
return ftpClient;
}
/*
* 从FTP服务器下载文件
*
* @param ftpHost FTP IP地址
* @param ftpUserName FTP 用户名
* @param ftpPassword FTP用户名密码
* @param ftpPort FTP端口
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param localPath 下载到本地的位置 格式:H:/download
* @param fileName 文件名称
*/
public static String downloadFtpFile(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort, String ftpPath, String localPath,
String fileName) {
FTPClient ftpClient = null;
try {
ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//String file = ftpPath.substring(ftpPath.lastIndexOf("/") + 1);
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory(ftpPath);
**InputStream is = ftpClient.retrieveFileStream(new String(fileName.getBytes("GBK"),ftpClient.DEFAULT_CONTROL_ENCODING));
if(is == null || ftpClient.getReplyCode()== FTPReply.FILE_UNAVAILABLE){
return "对不起,没有指定的文件";
}
if(is != null) {**加粗样式**
File localFile = new File(localPath + File.separatorChar + fileName);
OutputStream os = new FileOutputStream(localFile);
ftpClient.retrieveFile(fileName, os);
os.close();
is.close();
ftpClient.completePendingCommand();
}
return fileName+"下载成功";**
} catch (FileNotFoundException e) {
System.out.println("没有找到" + ftpPath + "文件");
e.printStackTrace();
return "没有找到" + ftpPath + "文件";
} catch (SocketException e) {
System.out.println("连接FTP失败.");
e.printStackTrace();
return "连接FTP失败.";
} catch (IOException e) {
e.printStackTrace();
System.out.println("文件读取错误。");
e.printStackTrace();
return "文件读取错误。";
}finally {
if(ftpClient != null){
try {
ftpClient.disconnect();
}catch (IOException e){
logger.error(e.getMessage());
}
}
}
}
/**
* Description: 向FTP服务器上传文件
* @param ftpHost FTP服务器hostname
* @param ftpUserName 账号
* @param ftpPassword 密码
* @param ftpPort 端口
* @param ftpPath FTP服务器中文件所在路径 格式: ftptest/aa
* @param fileName ftp文件名称
* @param input 文件流
* @return 成功返回true,否则返回false
*/
public static boolean uploadFile(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort, String ftpPath,
String fileName,InputStream input) {
boolean success = false;
FTPClient ftpClient = null;
try {
int reply;
ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
return success;
}
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory(ftpPath);
ftpClient.storeFile(fileName, input);
input.close();
ftpClient.logout();
success = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException ioe) {
}
}
}
return success;
}
}
改进的后的Service代码:
@Service
public class FtpService {
@Autowired
private FTPUtils ftpUtils;
private static final Logger logger = LoggerFactory.getLogger(FtpService.class);
//由于下载和上传ftp服务器的地址可能不一致,所以下载和上传的ftp地址分开
@Value("${ftphost}")
private String ftpHost;
@Value("${ftpusername}")
private String ftpUserName;
@Value("${ftppassword}")
private String ftpPassword;
@Value("${ftpport}")
private String ftpPort;
@Value("${ftppath}")
private String ftpPath;
@Value("${ftplocalpath}")
private String localPath;
/**
* ftp文件上传
* @param file 需要上传的文件
* @return
* @throws IOException
*/
public String Upload(MultipartFile file) throws IOException {
String filename = file.getOriginalFilename();
InputStream inputStream = file.getInputStream();
boolean flag= ftpUtils.uploadFile( "192.168.43.84", "fanyusong","123456", 21,"/",filename, inputStream);
if (flag){
return "上传成功";
}
return "上传失败";
}
/**
* ftp文件下载
* @param fileName ftp需要下载的文件名
* @return
*/
public String Download(String fileName){
int ftpPathInt = Integer.parseInt(ftpPort);
return ftpUtils.downloadFtpFile(ftpHost, ftpUserName,ftpPassword,ftpPathInt,ftpPath,localPath, fileName);
}
}
改进后的Controller代码:
@RestController
@RequestMapping("/ftp")
public class FtpController {
@Autowired
private FtpService ftpService;
@ApiOperation(value = "ftp上传", notes = "ftp上传")
@PostMapping("/upfile")
public JsonResponse Upload(MultipartFile file) throws Exception {
return JsonResponseUtil.success(ftpService.Upload(file));
}
/**
* ftp下载
* @param fileName
* @return
* @throws Exception
*/
@ApiOperation(value = "ftp下载", notes = "ftp下载")
@GetMapping("/downfile")
public JsonResponse Download(@RequestParam String fileName) throws Exception {
return JsonResponseUtil.success(ftpService.Download(fileName));
}
}
重新配置的yml文件:
#ftp下载地址配置
ftphost: 192.168.43.84
ftpusername: fanyusong
ftppassword: 123456
ftpport: 21
ftppath: “/”
ftplocalpath: F:\FTPDownload
因为之前是用依赖包,但是相反的加重了代码还不好管理配置,所以此处删除了依赖
本人是做一个功能写一篇博客,别的不说,每次遇到问题网上各种找思路,很累,因为没有完全相同的需求,我写一些也让别人有相似的需求的时候可以参考一下,都是学习路上踩坑的人,相互学习借鉴让路没有那么难走
越努力越幸运,加油!