FTPS的上传功能和遇到的问题

716 阅读2分钟

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就可以成功导入