Java使用FTP、FTPS上传文件

Updated on in 程序人生 with 0 views and 0 comments

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 {

    }
}

标题:Java使用FTP、FTPS上传文件
作者:wenyl
地址:http://www.wenyoulong.com/articles/2020/06/16/1592293604521.html