java操作SFTP

简介: java操作SFTP

引言


最近项目中对接了几个将客户,在案件传输的时候都采用SFTP + excel 或者 csv的方式传输,下面分享一下小编在项目中对sftp操作的封装的工具类。同时分享一下在实际中的应用。


1、相关包依赖


<dependency>
            <groupId>org.apache.sshd</groupId>
            <artifactId>sshd-sftp</artifactId>
            <version>2.0.0</version>
        </dependency>
        <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.54</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.trilead/trilead-ssh2 -->
        <dependency>
            <groupId>com.trilead</groupId>
            <artifactId>trilead-ssh2</artifactId>
            <version>1.0.0-build221</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3</version>
        </dependency>

2、SFTPutil工具类

package com.jack.cmbc.tools;
import com.jcraft.jsch.*;
import org.apache.poi.util.IOUtils;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
/**
 * Created by zhenghao on 2018/9/18.
 */
public class SFTPUtil {
    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 SFTPUtil(String username, String password, String host, int port) {
        this.username = username;
        this.password = password;
        this.host = host;
        this.port = port;
    }
    /**
     * 构造基于秘钥认证的sftp对象
     */
    public SFTPUtil(String username, String host, int port, String privateKey) {
        this.username = username;
        this.host = host;
        this.port = port;
        this.privateKey = privateKey;
    }
    public SFTPUtil() {
    }
    /**
     * 连接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 void cd(String directory) throws SftpException {
        if (directory != null && !"".equals(directory) && !"/".equals(directory)) {
            sftp.cd(directory);
        }
    }
    /**
     * 下载文件。
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件
     * @param saveFile     存在本地的路径
     */
    public void download(String directory, String downloadFile, String saveFile) {
        System.out.println("download:" + directory + " downloadFile:" + downloadFile + " saveFile:" + saveFile);
        File file = null;
        try {
            if (directory != null && !"".equals(directory)) {
                sftp.cd(directory);
            }
            file = new File(saveFile);
            sftp.get(downloadFile, new FileOutputStream(file));
        } catch (SftpException e) {
            e.printStackTrace();
            if (file != null) {
                file.delete();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            if (file != null) {
                file.delete();
            }
        }
    }
    /**
     * 下载文件
     *
     * @param directory    下载目录
     * @param downloadFile 下载的文件名
     * @return 字节数组
     */
    public byte[] download(String directory, String downloadFile) throws SftpException, IOException {
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        InputStream is = sftp.get(downloadFile);
        byte[] fileData = IOUtils.toByteArray(is);
        return fileData;
    }
    /**
     * 删除文件
     *
     * @param directory  要删除文件所在目录
     * @param deleteFile 要删除的文件
     */
    public void delete(String directory, String deleteFile) throws SftpException {
        if (directory != null && !"".equals(directory)) {
            sftp.cd(directory);
        }
        sftp.rm(deleteFile);
    }
    /**
     * 列出目录下的文件
     *
     * @param directory 要列出的目录
     */
    public Vector<?> listFiles(String directory) throws SftpException {
        return sftp.ls(directory);
    }
    public boolean isExistsFile(String directory, String fileName) {
        List<String> findFilelist = new ArrayList();
        ChannelSftp.LsEntrySelector selector = new ChannelSftp.LsEntrySelector() {
            @Override
            public int select(ChannelSftp.LsEntry lsEntry) {
                if (lsEntry.getFilename().equals(fileName)) {
                    findFilelist.add(fileName);
                }
                return 0;
            }
        };
        try {
            sftp.ls(directory, selector);
        } catch (SftpException e) {
            e.printStackTrace();
        }
        if (findFilelist.size() > 0) {
            return true;
        } else {
            return false;
        }
    }
    //上传文件测试
    public static void main(String[] args) throws SftpException, IOException {
        SFTPUtil sftp = new SFTPUtil("xxx", "xxx", "xx.com.cn", 22);
        sftp.login();
        File file = new File("/Volumes/work/new1.xlsx");
        InputStream is = new FileInputStream(file);
        //sftp.upload("/test", "", "test_sftp.jpg", is);
        sftp.logout();
    }
}

3、下载文件使用

package com.jack.xxxx.service;
import com.jack.xxxx.tools.FileUtils;
import com.jack.xxxx.tools.GPGUtil;
import com.jack.xxxx.tools.SFTPUtil;
import com.jack.common.exception.TpErrorCodeGeneral;
import com.jack.common.model.BaseResult;
import com.jack.common.utils.DateUtils;
import com.jack.common.utils.service.ErrorLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
 * @Description:
 * @author: zhenghao
 * @date: 2019/6/12 10:04
*/
@Service
public class XiaoMiFtpService {
    @Resource
    ErrorLogService errorLogService;
    @Autowired
    private XiaoMiNotifyService notifyService;
    @Value("${xiaomi_ftp_host}")
    private String xiaomiFtpHost;
    @Value("${xiaomi_ftp_port}")
    private String xiaomiFtpPort;
    @Value("${xiaomi_ftp_user}")
    private String xiaomiFtpUser;
    @Value("${xiaomi_prikey_file}")
    private String xiaomiPriKeyFile;
    @Value("${xiaomi_ftp_local_file_path}")
    private String XIAOMI_LOCAL_FilPath;
    private static final String SFTPDirectory = "/home";
    private static String todayDownLoadFile = null;
    private static String todayCsvFilePath = null;
    private static String todayGpgFilePath = null;
    private boolean firstExistsFileFlag = false;
    /**
     * 为了保证服务器上文件上传结束,做一次文件保护
     */
    public void sync( int times) {
        String localFilePath = this.initLocalFilePath();
        //zhiqing6.12-1.xlsx ==zhiqing月份.几号-当天第几次.xlsx
        String gpgFileName = "zhiqing" + DateUtils.getCurrentMonth() + "." + DateUtils.getCurrentDay() + "-" + times +".xlsx";
        //判断今日是否下载成功了文件
        if (gpgFileName.equals(todayDownLoadFile)) {
            System.out.println(DateUtils.getStrDate()+ " 今日文件已经下载:" + todayDownLoadFile);
            return;
        }
        //判断本地是否存在文件
        if (isLocalFileExists(localFilePath + "/" + gpgFileName)) {
            System.out.println(DateUtils.getStrDate()+" 本地文件已经存在:" + gpgFileName);
            return;
        }
        //初始化服务器链接
        SFTPUtil sftpUtil = this.initFtp();
        if (sftpUtil == null) {
            writeErrorMsg("initFtp failed");
            return;
        }
        //判断服务器上
        if (!sftpUtil.isExistsFile(SFTPDirectory, gpgFileName)) {
            System.out.println(DateUtils.getStrDate()+" 服务器上不存在文件:" + gpgFileName);
            closeFtp(sftpUtil);
            return;
        }
        if (!firstExistsFileFlag) {
            System.out.println(DateUtils.getStrDate()+" 第一次发现文件存在:" + gpgFileName);
            firstExistsFileFlag = true;
            closeFtp(sftpUtil);
            return;
        }
        //下载文件
        String downloadFile = downloadFtpFiles(sftpUtil, localFilePath, gpgFileName);
        System.out.println(DateUtils.getStrDate()+" 下载文件:" + downloadFile);
        if (downloadFile != null) {
            todayDownLoadFile = gpgFileName;
            todayGpgFilePath = localFilePath + "/" + gpgFileName;
            todayCsvFilePath = downloadFile;
            writeErrorMsg("今日文件下载完成:" + todayDownLoadFile);
            firstExistsFileFlag = false;
            //通知业务系统进行文件处理 参数为文件全路径
            notifyService.notifyFilesChanged(downloadFile);
        }
        closeFtp(sftpUtil);
    }
    private String downloadFtpFiles(SFTPUtil sftpUtil, String localFilePath, String fileName) {
        String downloadFileName = null;
        try {
            sftpUtil.cd(SFTPDirectory);
            sftpUtil.download(SFTPDirectory, fileName, localFilePath + "/" + fileName);
            if (fileName.endsWith(".xlsx")) {
                downloadFileName = localFilePath + "/" + fileName;
            }
            if (downloadFileName != null) {
                File file = new File(downloadFileName);
                if (!file.exists()) {
                    System.out.println("本地不存在" + downloadFileName);
                    downloadFileName = null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return downloadFileName;
    }
    private SFTPUtil initFtp() {
        //基于秘钥链接sftp
        SFTPUtil sftp = new SFTPUtil(xiaomiFtpUser, xiaomiFtpHost, Integer.valueOf(xiaomiFtpPort),xiaomiPriKeyFile);
        sftp.login();
        System.out.println("login successed");
        return sftp;
    }
    private void closeFtp(SFTPUtil sftp) {
        try {
            sftp.logout();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private boolean isLocalFileExists(String filePathName) {
        File file = new File(filePathName);
        if (file.exists()) {
            return true;
        } else {
            return false;
        }
    }
    private String initLocalFilePath() {
        String filePath = XIAOMI_LOCAL_FilPath;
        File file = new File(filePath);
        file.mkdirs();
        return filePath;
    }
    private void writeErrorMsg(String msg) {
        System.out.println(DateUtils.date2FullStr(new Date()) + "=====" + msg);
        errorLogService.writeErrorLog("", msg);
    }
}

4、定时任务调用

package com.jack.xxxx.task;
import com.jack.xxxx.service.xxxxFtpService;
import com.jack.xxxx.service.XiaoMiFtpService;
import com.jack.common.utils.DateUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
 * @Description: 
 * @author: zhenghao
 * @date: 2019/6/12 16:30
*/
@Component
public class SynXiaoMiFtpTask {
    @Resource
    XiaoMiFtpService xiaoMiFtpService;
    /**
     * @Description: 第一次 导入
     * @author: zhenghao
     * @date: 2019/6/12 16:33
    */
    @Scheduled(cron = "0 0/2 09 * * ? ")
    public void firsRrunTask() {
        System.out.println(DateUtils.getStrDate() + " 小米第一次runTask");
        try {
            xiaoMiFtpService.sync(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

5、配置文件

#sftp地址
xiaomi_ftp_host=xxx.com
xiaomi_ftp_user=xxx
xiaomi_ftp_port=2222
xiaomi_ftp_local_file_path=/xmdata
#秘
xiaomi_prikey_file =/root/xx
xiaomi_notify_host_url = http://xx.xx.xx.xx.:8096/xx/xx/xx

6、小结


以上最近使用sftp传送数据的总结,希望对读者有些帮助!


目录
相关文章
|
4月前
|
Java BI 数据处理
如何在Java中实现Excel操作
如何在Java中实现Excel操作
|
5月前
|
存储 Java
java用modbus4j的RTU去操作那些寄存器(线圈,保持,输入,离散输入寄存器)
java用modbus4j的RTU去操作那些寄存器(线圈,保持,输入,离散输入寄存器)
125 0
|
5月前
|
Java 数据库 数据安全/隐私保护
Java操作Excel文件导入导出【内含有 jxl.jar 】
Java操作Excel文件导入导出【内含有 jxl.jar 】
81 0
|
4月前
|
存储 Java 索引
Java ArrayList操作指南:如何移除并返回第一个元素
通过上述方法,你可以方便地从Java的 `ArrayList` 中移除并返回第一个元素。这种操作在日常编程中非常常见,是处理列表时的基本技能之一。希望这篇指南能帮助你更好地理解和运用Java的 `ArrayList`。
48 4
|
4月前
|
分布式计算 DataWorks Java
DataWorks操作报错合集之使用ODPS Tunnel Upload功能时,遇到报错:Java 堆内存不足,该如何解决
DataWorks是阿里云提供的一站式大数据开发与治理平台,支持数据集成、数据开发、数据服务、数据质量管理、数据安全管理等全流程数据处理。在使用DataWorks过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
|
4月前
|
SQL 缓存 Java
使用MyBatis优化Java持久层操作
使用MyBatis优化Java持久层操作
|
4月前
|
Java API 开发者
Java中的文件I/O操作详解
Java中的文件I/O操作详解
|
4月前
|
Java BI 数据处理
如何在Java中实现Excel操作
如何在Java中实现Excel操作
|
5月前
|
Java
使用kafka-clients操作数据(java)
使用kafka-clients操作数据(java)
|
5月前
|
安全 Java 程序员
在Java中,finalization是一种机制,允许对象在被垃圾收集器回收之前执行一些清理操作。
【6月更文挑战第24天】Java中的finalization机制允许对象在被垃圾收集前执行清理,以释放系统资源或处理敏感信息。`finalize()`方法用于定义此类操作,但它不是可靠的资源管理策略,因为调用时机不确定且可能影响性能。尽管可用于清理外部资源或作为保护措施,但应避免依赖finalization,而应优先采用手动资源管理,遵循“创建者负责”原则。
30 1