SFTP文件上传OSS并解析入库

情景假设:我们有一个学生信息数据,需要从SFTP解析入库,但是因为隔离装置的问题无法直接读取,需要转移到OSS平台(OSS与SFTP可以互相访问)再解析入库。

目录

一、思路

二、获取SFTP文件 

三、OSS上传

四、总结


一、思路

1、首先明确思路。如下图所示:

学生类:

@Data
public class Students {
    private String name;

    private String age;

    private String score;
}

二、获取SFTP文件 

1、SFTP配置

        我们要明确sftp服务器主机IP地址、端口、账号、密码等信息,通过读取配置文件获取SFTP的配置信息并创建SFTP通道:

    @Value("${ftp.hosts}")
    private String hosts;      //sftp地址
    @Value("${ftp.port}")
    private String port;       //sftp端口
    @Value("${ftp.username}")
    private String username;    //sftp用户名
    @Value("${ftp.password}")
    private String password;    //sftp密码
    @Value("${ftp.filePath}")
    private String filePath;    //stfp文件保存位置

定义全局静态变量,并通过以上信息创建sftp通道,实现文件的上传、下载

private static Session session = null;    //用于保存登录时的session信息
private static ChannelSftp channel = null;    //保存ChannelSftp 的通道
    /**
     * 创建一个sftp通道
     */
    public static ChannelSftp getSftp(String hosts, String port, String username, String password){
        JSch jSch = new JSch();
        //根据主机IP、端口、用户名创建一个session对象
        try {
            session = jSch.getSession(username, hosts, Integer.parseInt(port));
            log.info("获取Session成功");
            if (StringUtils.isNoneBlank(password)) {
                session.setPassword(password);
            }
            Properties properties = new Properties();
            properties.put("StrictHostKeyChecking", "no");
            session.setConfig(properties);  //为session对象设置properties
            session.setTimeout(2000);       //设置session过期时间
            session.connect();
            log.info("开始成功");
            channel = (ChannelSftp) session.openChannel("sftp");    //打开sftp通道
            channel.connect();
            log.info("成功连接sftp服务器!!!");
        } catch (JSchException e) {
            e.printStackTrace();
            log.error(("获取Session失败,请检查用户名、主机IP、端口号"));
        }
        return channel;
    }

当不需要sftp通道时需要关闭channel和session,避免资源浪费

/**
 * 关闭channel和session
 */
public static void shutDownChannel(){
    if (channel != null){
        channel.disconnect();
    }
    if (session != null){
        session.disconnect();
    }
}

2、SFTP文件上传

/**
     * SFTP文件上传
     *
     * @param uploadFile 需要上传的文件
     */
    public boolean UploadToSftp(File uploadFile) {
        //定义返回值
        boolean flag = true;
        //获取channelSftp对象
        ChannelSftp channelSftp = SftpChannel.getSftp(hosts, port, username, password);
        //判断文件路径是否存在
        try {
            Vector dir = channelSftp.ls(filePath);
            //文件夹不存在则创建这个文件夹
            if (dir.isEmpty()) {
                channelSftp.mkdir(filePath);
            }
            String destFilePath = filePath + uploadFile.getName();
            //文件上传
            try {
                channelSftp.put(new FileInputStream(uploadFile), destFilePath);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                flag = false;
                log.error("文件上传异常");
            }
        } catch (SftpException e) {
            e.printStackTrace();
            flag= false;
            log.error("文件路径异常");
        } finally {
            if (channelSftp != null) {
                channelSftp.quit();
            }
            try {
                SftpChannel.shutDownChannel();
            } catch (Exception e) {
                e.printStackTrace();
                log.error("channel或session关闭失败");
            }
        }
        return flag;
    }

3、获取下载文件输入流

public Map<String,Object> downSftpFile(ChannelSftp sftp){
        Map<String,Object> resultMap = new HashMap<>();
        InputStream inputStream = null;
        try {
            if (StringUtils.isNoneBlank(filePath)) {
                sftp.cd(filePath);//进入所在路径
            }
            Vector vector = sftp.ls("./");
            for (Object o : vector) {
                ChannelSftp.LsEntry file = (ChannelSftp.LsEntry) o;
                //文件名称
                String fileName = file.getFilename();
                if (StringUtils.isNoneBlank(fileName) && !fileName.startsWith(".")) {
                    inputStream = sftp.get(fileName);
                }
                resultMap.put("filename",fileName);
                resultMap.put("inputStream",inputStream);
            }
        } catch (SftpException e) {
            e.printStackTrace();
            resultMap.put("error","error");
            log.error("下载失败:"  +e);
        }finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    log.error("下载输入流关闭失败:" +  e);
                }
            }
        }
        return resultMap;
    }

三、OSS上传

1、OSS配置

        我们要明确OSS的配置信息信息,通过读取配置文件获取OSS的配置信息:

    @Value("${oss.endpoint}")
    private String endpoint;      //oss域名
    @Value("${oss.accessKey}")
    private String accessKey;       //oss 资源管理器账号
    @Value("${oss.accessSecret}")
    private String accessSecret;    //oss 资源管理密码
    @Value("${oss.bucketName}")
    private String bucketName;    //oss  bucketName
    @Value("${oss.filePath}")
    private String filePath;    //oss文件保存位置

2、OSS文件上传 

    /**
     * 文件上传
     * @param filename  上传文件名
     * @param inputStream   上传文件输入流
     * @return
     */
    public Map<String, String> uploadfile(String filename, InputStream inputStream) {
        Map<String, String> mapresult = new HashMap<>();
        Date date = new Date();
        String path = bucketName + "自定义文件路径";
        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
        // 私有云要关闭CNAME
        conf.setSupportCname(false);
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, accessSecret, conf);
        if (ossClient != null && ossClient.doesBucketExist(bucketName)) {
            log.info("****************cunzai****************");
        } else {
            log.info("****************bu cunzai****************");
        }
        try {
            if (ossClient != null) {
                ossClient.putObject(bucketName, path + "/" + filename, inputStream);
                log.info("上传成功");
                ossClient.shutdown();
            }
        } catch (Exception e) {
            log.info("上传失败");
            mapresult.put("msg", "操作失败");
            log.error(String.valueOf(e));
        } finally {
            if (null != ossClient) {
                ossClient.shutdown();
            }
        }
        return mapresult;
    }

3、SFTP文件上传到OSS

此时我们可以实现SFTP文件上传到OSS。

        InputStream inputStream = null;
        SftpChannel sftpChannel = new SftpChannel();
        OssUtils ossUtils = new OssUtils();
        ChannelSftp sftp = SftpChannel.getSftp(hosts, port, username, password);
        Map<String, Object> map = sftpChannel.downSftpFile(sftp);
        String error = (String) map.get("error");
        if (StringUtils.isNotEmpty(error) && error.equals("error")) {
            return;
        }
        try {
            String filename = (String) map.get("filename");
            inputStream = (InputStream) map.get("inputStream");
            if (StringUtils.isNotEmpty(filename) && ObjectUtil.isNotEmpty(inputStream)){
                try {
                    ossUtils.uploadfile(filename,inputStream);
                } catch (Exception e) {
                    log.error("OSS文件上传失败");
                }
            }
        } catch (Exception e) {
            log.error("SFTP文件读取失败");
        }finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

4、OSS文件下载读取

public List<String> downloadFilestream(String filename) {
        List<String> list = new ArrayList<>();
        String path = "文件夹路径";
        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
        String objectName = path + "/" + filename;
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, accessSecret);
        try {
            // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
            BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
            while (true) {
                String line = reader.readLine();
                if (line == null) break;
                else list.add(line);
            }
            // 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
            reader.close();
            // ossObject对象使用完毕后必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
            ossObject.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return list;
    }

5、文件解析入库

这样我们就可以补齐“SFTP文件上传到OSS”代码,实现文件解析入库

InputStream inputStream = null;
        SftpChannel sftpChannel = new SftpChannel();
        Students students = new Students();
        OssUtils ossUtils = new OssUtils();
        ChannelSftp sftp = SftpChannel.getSftp(hosts, port, username, password);
        Map<String, Object> map = sftpChannel.downSftpFile(sftp);
        String error = (String) map.get("error");
        if (StringUtils.isNotEmpty(error) && error.equals("error")) {
            return;
        }
        try {
            String filename = (String) map.get("filename");
            inputStream = (InputStream) map.get("inputStream");
            if (StringUtils.isNotEmpty(filename) && ObjectUtil.isNotEmpty(inputStream)){
                try {
                    ossUtils.uploadfile(filename,inputStream);
                    List<String> list = ossUtils.downloadFilestream(filename);
                    for (String str : list) {
                        String[] split = str.split("\\t");
                        students.setName(split[0]);
                        students.setAge(split[1]);
                        students.setScore(split[2]);
                    }
                } catch (Exception e) {
                    log.error("OSS文件上传失败");
                }
            }
        } catch (Exception e) {
            log.error("SFTP文件读取失败");
        }finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

四、总结

这样我们就实现了我们的目的,成功的把SFTP中的学生文件转移到OSS并解析到我们的数据库。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一个简单的 shell 脚本,用于上文件到远程服务器的 SFTP,并在上完成后进行文件校验: ``` #!/bin/bash # 服务器信息 host="remote.server.com" username="username" password="password" # 本地文件路径和名称 local_file="/path/to/local/file" remote_file="/path/to/remote/file" # 上文件SFTP sftp -oBatchMode=no -b - $username@$host << END_SCRIPT put $local_file $remote_file quit END_SCRIPT # 获取远程文件的 MD5 校验值 remote_md5=$(ssh $username@$host "md5sum $remote_file" | awk '{print $1}') # 获取本地文件的 MD5 校验值 local_md5=$(md5sum $local_file | awk '{print $1}') # 比较 MD5 校验值 if [ "$local_md5" == "$remote_md5" ]; then echo "文件并校验成功!" else echo "文件失败或校验不通过!" fi ``` 在脚本中,您需要将 `host`、`username` 和 `password` 替换为您的远程服务器信息。`local_file` 和 `remote_file` 变量则指定要上的本地文件路径和名称以及远程服务器上的文件路径和名称。 脚本使用 `sftp` 命令将本地文件到远程服务器上。然后,它使用 `ssh` 命令获取远程文件的 MD5 校验值,并使用 `md5sum` 命令获取本地文件的 MD5 校验值。最后,脚本比较这两个值以确保文件已成功上并且校验通过。 您可以将此脚本保存为 `.sh` 文件,然后使用 `chmod +x script.sh` 命令使其可执行。接下来,您可以通过在终端中输入脚本名称来运行它。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值