FTPS的上传功能和遇到的问题
package tianrun.ziguan.api.config.info.service.ftpUploadService.impl;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import tianrun.ziguan.api.common.core.base.ResultBody;
import tianrun.ziguan.api.common.core.resttemplate.IRestTemplateService;
import tianrun.ziguan.api.config.info.domain.FtpServiceConstant;
import tianrun.ziguan.api.config.info.dto.request.upload.ReqImageBody;
import tianrun.ziguan.api.config.info.dto.request.upload.ReqUploadUrlBody;
import tianrun.ziguan.api.config.info.dto.response.ftpupload.RepPathBody;
import tianrun.ziguan.api.config.info.service.ftpUploadService.IFtpUploadService;
import tianrun.ziguan.api.config.info.utils.SSLSessionReuseFTPSClient;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
/**
* @ClassName: FtpUploadServiceImpl
* @Author ddy
* @Date 2021/11/16
* @Version 1.0
**/
@Service
public class FtpUploadServiceImpl implements IFtpUploadService {
private static final Logger log = LoggerFactory.getLogger(FtpUploadServiceImpl.class);
private final String getSaveFTPUrl;
private final String getDeptImage;
private final String getFtpUrl;
private final IRestTemplateService restTemplateService;
@Autowired
private RestTemplate restTemplate;
public FtpUploadServiceImpl(@Value("${ziguan.services.pvmonitoring.saveFTPUrl}") String getSaveFTPUrl,
@Value("${ziguan.services.pvmonitoring.getDeptImage}") String getDeptImage,
@Value("${FTP.Url}") String getFtpUrl,
IRestTemplateService restTemplateService) {
this.getSaveFTPUrl = getSaveFTPUrl;
this.getDeptImage = getDeptImage;
this.getFtpUrl = getFtpUrl;
this.restTemplateService = restTemplateService;
}
/**
* @param photo 上传的文件
* @Author daidayang
* @Date 2021/11/17
* @Return
* @Version 1.0
**/
@Override
public ResultBody upLoading(MultipartFile photo, String deptId) {
//首先连接到FTP客户端
FTPSClient ftpClient = getFTPClient(FtpServiceConstant.FTPHOST, FtpServiceConstant.FTPUSERNAME, FtpServiceConstant.FTPPASSWORD, FtpServiceConstant.FTPPORT);
//然后在把文件转换成输入流
RepPathBody repPathBody = new RepPathBody();
ResultBody resultBody = null;
try {
InputStream inputStream = photo.getInputStream();
int replyCode = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(replyCode)) {
ftpClient.disconnect();
return resultBody;
}
ftpClient.setControlEncoding("UTF-8"); // 中文支持
ftpClient.execPROT("P");
ftpClient.execPBSZ(10240);
//设置缓冲区
ftpClient.setBufferSize(10240);
//设置为被动模式
ftpClient.enterLocalPassiveMode();
//存储目录
ftpClient.changeWorkingDirectory(FtpServiceConstant.FTPPATH);
//文件名
String originalFilename = photo.getOriginalFilename();
int typeIndex = originalFilename.lastIndexOf(".");
String type = originalFilename.substring(typeIndex);
String realFileNname = originalFilename.substring(0, typeIndex);
String fileName=realFileNname+ StringPool.UNDERSCORE +deptId+type;
System.out.println(fileName);
//指定文件类型
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
//首先查找出此部门ID对应的是FTP里面的哪个文件
ReqUploadUrlBody deptImage = new ReqUploadUrlBody();
deptImage.setDeptId(Long.valueOf(deptId));
ReqImageBody imageString = restTemplateService.post(getDeptImage, "s",deptImage,ReqImageBody.class);
String imagePath = imageString.getData();
System.out.println(imageString);
//如果数据库里面没有存在就直接存储
if (ObjectUtils.isNull(imagePath)){
ftpClient.storeFile(new String(fileName.getBytes("UTF-8"),"iso-8859-1"), inputStream);
}else {//如果有就去FTP上查找出来然后删除
int i = imagePath.lastIndexOf("/");
String imageName = imagePath.substring(i);
//这边在去FTP里面查找
String[] listNames = ftpClient.listNames(FtpServiceConstant.FTPPATH + imageName);
boolean existsFlag = listNames.length > 0;
System.out.println(existsFlag ? "文件存在" : "文件不存在");
if (existsFlag){
ftpClient.deleteFile(FtpServiceConstant.FTPPATH + imageName);
ftpClient.storeFile(new String(fileName.getBytes("UTF-8"),"iso-8859-1"), inputStream);
}
}
inputStream.close();
ftpClient.logout();
ftpClient.disconnect();
resultBody = new ResultBody(getFtpUrl +fileName);
} catch (IOException e) {
e.printStackTrace();
}finally {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
} catch (IOException ioe) {
}
}
}
return resultBody;
}
/**
* @param ftpHost FTP主机服务器
* @param ftpUserName FTP 登录密码
* @param ftpPassword FTP登录用户名
* @param ftpPort FTP端口 默认为21
* @Author ddy
* @Date 2021/11/16
* @Return 获取FTP服务端
* @Version 1.0
**/
public FTPSClient getFTPClient(String ftpHost, String ftpUserName,
String ftpPassword, int ftpPort) {
// FTPSClient ftpClient = new FTPSClient("SSL",false);
FTPSClient ftpClient = new SSLSessionReuseFTPSClient();
// FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(ftpHost, ftpPort);// 连接FTP服务器
if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
System.out.println("FTP连接成功。");
boolean login = ftpClient.login(ftpUserName, ftpPassword);
System.out.println(login);
if(ftpClient.login(ftpUserName, ftpPassword)){
System.out.println("登录成功");
}// 登陆FTP服务器
} else {
System.out.println("未连接到FTP,用户名或密码错误。");
ftpClient.disconnect();
}
} catch (SocketException e) {
e.printStackTrace();
System.out.println("FTP的IP地址可能错误,请正确配置。");
} catch (IOException e) {
e.printStackTrace();
System.out.println("FTP的端口错误,请正确配置。");
}
catch (Exception e){
e.printStackTrace();
}
return ftpClient;
}
}
遇到的问题 FTP和FTPS在上传文件时都要开启被动模式,否则文件没有存入进ftp服务器
FTPS在上传文件时,如果报522 SSL connection failed,就需要去FTP服务器上去配置SSL的可重用SSL通道,需要把require_ssl_reuse=YES设置成NO就可以成功导入