Springboot使用Sftp实现服务器文件上传下载

提示:文章如有错误的地方请指出,以免误人子弟!


提示:以下是本篇文章正文内容,下面案例可供参考

一、导入maven jar包

maven 地址

<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>

二、上代码

  1. application.yml (根据自己业务来添加路径地址,用不上的可以删掉,我这里就不删了)
sftp:
  # 服务器地址
  host: 192.168.96.135
  # 端口
  port: 22
  # 账号
  userName: root
  # 密码
  password: wang521
  # 图片的根路径
  basePath: /home/nginx/image
  # 音频的根路径
  audioPath: /home/nginx/audio
  # 视频的根路径
  videoPath: /home/nginx/video
  # channel连接超时时间
  timeout: 30000
  #连接次数
  count: 10
  #休眠时间
  sleepTime: 6000
  #服务器头像地址
  titleImgsPath: http://192.168.96.135:80/image/
  #服务器音频地址
  titleAudiosPath: http://192.168.96.135:80/audio/
  #服务器视频地址
  titleVideosPath: http://192.168.96.135:80/video/
  1. 新建一个实体类,用起来方便的
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;

import java.io.Serializable;

/**
 * @author Mr.Tiger
 * @date 2021/01/07 17:59
 */
@Data
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class SftpDTO implements Serializable {
    /**
     * description: Ip
     */
    private String hostname;
    /**
     * description: 端口
     */
    private Integer port;
    /**
     * description: 服务器用户名
     */
    private String username;
    /**
     * description: 服务器密码
     */
    private String password;
    /**
     * description: 连接超时
     */
    private Integer timeout;
    /**
     * description: 服务器根路径
     */
    private String remoteRootPath;

	public SftpDTO() {}
    public SftpDTO(String hostname, Integer port, String username, String password, Integer timeout, String remoteRootPath) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;
        this.timeout = timeout;
        this.remoteRootPath = remoteRootPath;
    }
}
  1. sftp工具类
    注意:
    这里有个地方需要注意下,单个文件或多个文件上传只需要连接一次 sftp 就好了
import com.jcraft.jsch.*;
import com.wwwh.onlyone.common.entity.userInfo.dto.SftpDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author Mr.Tiger
 * @date 2021/01/07 18:17
 */
@Slf4j
@Component
@RefreshScope
public class SftpUtil
{
    /**
     * description: count-> 连接超过次数,线程休眠
     */
    @Value("${sftp.count}")
    private long count;
    /**
     * description: sleepTime-> 休眠时间
     */
    @Value("${sftp.sleepTime}")
    private long sleepTime;

    /**
     * description: count1-> 已经连接次数
     */
    private long count1 = 0;

    /**
     * description: 连接sftp服务器
     *
     * @param sftpConfig sftp实体类
     * @return com.jcraft.jsch.ChannelSftp
     * @author Mr.Tiger
     */
    public ChannelSftp connect(SftpDTO sftpConfig) {
        ChannelSftp sftp = null;
        try {
            JSch jsch = new JSch();
            jsch.getSession(sftpConfig.getUsername(), sftpConfig.getHostname(), sftpConfig.getPort());
            Session sshSession = jsch.getSession(sftpConfig.getUsername(), sftpConfig.getHostname(), sftpConfig.getPort());
            log.info("Session created ... UserName=" + sftpConfig.getUsername() + ";host=" + sftpConfig.getHostname() + ";port=" + sftpConfig.getPort());
            sshSession.setPassword(sftpConfig.getPassword());
            Properties sshConfig = new Properties();
            sshConfig.put("StrictHostKeyChecking", "no");
            sshSession.setConfig(sshConfig);
            sshSession.connect();
            log.info("Session connected ...");
            //协议
            Channel channel = sshSession.openChannel("sftp");
            channel.connect();
            sftp = (ChannelSftp) channel;
            log.info("登录成功");
        } catch (Exception e) {
            try {
                count1 += 1;
                if (count == count1) {
                    throw new RuntimeException(e);
                }
                Thread.sleep(sleepTime);
                log.info("重新连接....");
                connect(sftpConfig);
            } catch (InterruptedException e1) {
                throw new RuntimeException(e1);
            }
        }
        return sftp;
    }

    /**
     * description: 关闭 流
     *
     * @param ins 输入流
     * @param file MultipartFile 转 File的文件
     * @return void 返回类型
     * @author Mr.Tiger
     */
    public static void inputStreamToFile(InputStream ins,File file) {
        try {
            OutputStream os = new FileOutputStream(file);
            int bytesRead = 0;
            byte[] buffer = new byte[8192];
            while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            ins.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * description: 上传文件
     *
     * @param file 要上传的文件
     * @param directory 上传的目录
     * @param sftpConfig sftp实体类
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    public Map<String, String> upload(MultipartFile file, String directory, SftpDTO sftpConfig, String fileName) {
        Map<String, String> map = new HashMap<String, String>(10);
        ChannelSftp sftp = connect(sftpConfig);
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            try {
                sftp.mkdir(directory);
                sftp.cd(directory);
                log.info("创建的路径为--:"+directory);
            } catch (SftpException e1) {
                throw new RuntimeException("ftp创建文件路径失败" + directory);
            }
        }
        InputStream inputStream = null;
        try
        {
            inputStream = file.getInputStream();
            sftp.put(inputStream, fileName);;
            map.put("code","200");
            log.info("文件头像成功");
        } catch (Exception e) {
            map.put("code","500");
            throw new RuntimeException("sftp异常" + e);
        } finally {
            disConnect(sftp);
            closeStream(inputStream,null);
        }
        return map;
    }

    /**
     * description: 上传多个文件
     *
     * @param file 要上传的文件
     * @param directory 上传的目录
     * @param sftp sftp连接对象
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    public void uploadList(MultipartFile file, String directory, ChannelSftp sftp, String fileName) {
        try {
            sftp.cd(directory);
        } catch (SftpException e) {
            try {
                sftp.mkdir(directory);
                sftp.cd(directory);
                log.info("创建的路径为--:"+directory);
            } catch (SftpException e1) {
                throw new RuntimeException("ftp创建文件路径失败" + directory);
            }
        }
        InputStream inputStream = null;
        try {
            inputStream = file.getInputStream();
            sftp.put(inputStream, fileName);
            log.info("文件上传成功");
        } catch (Exception e) {
            throw new RuntimeException("sftp异常" + e);
        } finally {
            closeStream(inputStream,null);
        }
    }

    /**
     * description: 下载文件
     *
     * @param directory 下载目录
     * @param downloadFileUrl 下载的文件名称
     * @param sftpConfig sftp 实体类
     * @return byte[]
     * @author Mr.Tiger
     */
    public byte[] download(String directory, String downloadFileUrl, SftpDTO sftpConfig) {
        ChannelSftp sftp = connect(sftpConfig);
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            //进到文件夹下
            sftp.cd(directory);
            if (log.isInfoEnabled()) {
                log.info("打开远程文件:[{}]", new Object[]{directory});
            }
            InputStream inputStream = sftp.get(downloadFileUrl);
            byteArrayOutputStream = new ByteArrayOutputStream();
            int n = 0;
            byte[] data = new byte[1024];
            while ((n = inputStream.read(data, 0, data.length)) != -1) {
                byteArrayOutputStream.write(data, 0, n);
            }
            return byteArrayOutputStream.toByteArray();
        } catch (Exception e) {
            if (log.isInfoEnabled()) {
                log.info("文件下载出现异常,[{}]", e);
            }
            throw new RuntimeException("文件下载出现异常,[{}]", e);
        } finally
        {
            if (byteArrayOutputStream != null)
            {
                try
                {
                    byteArrayOutputStream.flush();
                }
                catch (IOException e)
                {
                    e.printStackTrace();
                }
            }
            disConnect(sftp);
        }
    }

    /**
     * description: 关闭流
     *
     * @param inputStream 输入流
     * @param outputStream 输出流
     * @return void
     * @author Mr.Tiger
     */
    private void closeStream(InputStream inputStream,OutputStream outputStream) {
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if(inputStream != null){
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * description: 删除文件
     *
     * @param directory 要删除文件所在目录
     * @param deleteFile 要删除的文件
     * @param sftpConfig sftp实体类
     * @return void 返回类型
     * @author Mr.Tiger
     */
    public void delete(String directory, String deleteFile, SftpDTO sftpConfig) {
        ChannelSftp sftp = null;
        try {
            sftp = connect(sftpConfig);
            sftp.cd(directory);
            sftp.rm(deleteFile);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally
        {
            disConnect(sftp);
        }
    }

    /**
     * description: 断掉连接
     *
     * @param sftp sftp实体类
     * @return void 返回类型
     * @author Mr.Tiger
     */
    public void disConnect(ChannelSftp sftp) {
        try {
            sftp.disconnect();
            sftp.getSession().disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  1. controller 使用
    单个,多个文件上传,单个文件下载,因为本人比较懒,这里把业务代码也贴上去了没有删掉,大家用的时候把没有的业务代码删掉就好了。因为这是cloud的项目,@RefreshScope删掉,@DubboReference替换成@Autowired或者@Resource。
import com.alibaba.fastjson.JSON;
import com.jcraft.jsch.ChannelSftp;
import com.wwwh.onlyone.common.entity.userInfo.doo.SysAudios;
import com.wwwh.onlyone.common.entity.userInfo.doo.SysVideos;
import com.wwwh.onlyone.common.entity.userInfo.dto.SftpDTO;
import com.wwwh.onlyone.common.service.registry.system.SysAudiosService;
import com.wwwh.onlyone.common.service.registry.system.SysEmpInfoService;
import com.wwwh.onlyone.common.service.registry.system.SysVideosService;
import com.wwwh.onlyone.common.util.createId.SnowFlakeGenerateIdWorker;
import com.wwwh.onlyone.common.util.responseJson.ResponseResult;
import com.wwwh.onlyone.consumer.util.RedisUtil;
import com.wwwh.onlyone.consumer.util.SftpUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author Mr.Tiger
 * @date 2021/01/07 19:07
 */
@Slf4j
@RestController
@RequestMapping("/sftpFile")
@RefreshScope
public class SftpController
{
    private final SftpUtil sftpUtil;
    public SftpController(SftpUtil sftpUtil)
    {
        this.sftpUtil = sftpUtil;
    }

    @DubboReference
    private SysEmpInfoService sysEmpInfoService;
    @DubboReference
    private SysAudiosService sysAudiosService;
    @DubboReference
    private SysVideosService sysVideosService;

    @Autowired
    private RedisUtil redisUtil;

    @Value("${sftp.host}")
    private String host;
    @Value("${sftp.port}")
    private int port;
    @Value("${sftp.userName}")
    private String userName;
    @Value("${sftp.password}")
    private String password;
    @Value("${sftp.timeout}")
    private int timeout;
    @Value("${sftp.basePath}")
    private String basePath;
    @Value("${sftp.audioPath}")
    private String audioPath;
    @Value("${sftp.videoPath}")
    private String videoPath;
    @Value("${sftp.titleImgsPath}")
    private String titleImgsPath;
    @Value("${sftp.titleAudiosPath}")
    private String titleAudiosPath;
    @Value("${sftp.titleVideosPath}")
    private String titleVideosPath;

    /**
     * description: 上传文件
     *
     * @param file 要上传的文件
     * @param userPhone 手机号(用户标识)
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    @PostMapping("/uploads")
    public String upload(MultipartFile file, String userPhone) {
        //获取文件名称
        String filename = file.getOriginalFilename();
        String fix = null;
        if (StringUtils.isNotBlank(filename)) {
            filename = filename.replace(" ", "");
            // 获取文件名后缀
            fix = filename.substring(filename.length() - 3);;
        }

        log.info("文件后缀---:"+fix);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(new Date());
        // 雪花算法, 生成id
        SnowFlakeGenerateIdWorker snowFlakeGenerateIdWorker = new SnowFlakeGenerateIdWorker(0L, 0L);
        String nextId = snowFlakeGenerateIdWorker.generateNextId();
        String fileName = nextId+"."+fix;
        //个人头像全路径
        String titleImgs = titleImgsPath+format+"/"+fileName;
        log.info("头像上传-存库路径---:"+titleImgs);
        //修改用户头像
        int i = sysEmpInfoService.updateUserTitleImg(titleImgs, userPhone);
        // 更新redis 中的头像地址
        redisUtil.hset(userPhone, "headImg", titleImgs);
        Map<String, String> upload = new HashMap<String, String>();
        if(i > 0) {
            String path = basePath + "/" + format;
            log.info("上传到服务器的路径--:"+path);
            SftpDTO sftpConfig = new SftpDTO(host,port,userName,password,timeout,path);
            upload = sftpUtil.upload(file, sftpConfig.getRemoteRootPath(), sftpConfig, fileName);
        }

        //头像地址返回前端
        upload.put("imgUrl",titleImgs);
        return JSON.toJSONString(upload);
    }

    /**
     * description: 下载文件
     *
     * @param imgFileName 下载的文件名称
     * @param downloadFileName 下载目录
     * @param response response
     * @author Mr.Tiger
     */
    @PostMapping("/downLoads")
    public void downLoad(String imgFileName, String downloadFileName, HttpServletResponse response) throws UnsupportedEncodingException {
        SftpDTO sftpConfig = new SftpDTO(host,port,userName,password,timeout,basePath);
        //需要下载的服务器文件目录
        String downloadFileUrl = sftpConfig.getRemoteRootPath() + "/" + imgFileName;
        byte[] bytes = sftpUtil.download(sftpConfig.getRemoteRootPath(), downloadFileUrl, sftpConfig);
        InputStream inputStream = new ByteArrayInputStream(bytes);
        response.setContentType("application/vnd.ms-excel;charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(downloadFileName, "UTF-8"));
        byte[] buffer = new byte[1024];
        //缓存字节流
        BufferedInputStream bufferedInputStream = null;
        //输出流
        OutputStream outputStream = null;
        try {
            outputStream = response.getOutputStream();
            bufferedInputStream = new BufferedInputStream(inputStream);
            int i = bufferedInputStream.read(buffer);
            while (i != -1) {
                outputStream.write(buffer, 0, i);
                i = bufferedInputStream.read(buffer);
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            if(bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null) {
                try {
                    outputStream.close();
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * description: 上传多个文件
     *
     * @param file 要上传的文件
     * @param type 文件类型
     * @param createName 上传人姓名
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author Mr.Tiger
     */
    @PostMapping("/uploadList")
    public ResponseResult uploadLists(List<MultipartFile> file, Integer type, String createName)
    {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String format = simpleDateFormat.format(new Date());
        SftpDTO sftpConfig = null;
        String path = null;
        List<SysAudios> sysAudiosList = null;
        List<SysVideos> sysVideosList = null;
        if (type != null) {
            // 1: 音频 2:视频
            if (type == 1) {
                path = audioPath + "/" + format;
                sysAudiosList = new ArrayList<>(file.size());
            }
            else {
                path = videoPath + "/" + format;
                sysVideosList = new ArrayList<>(file.size());
            }
            log.info("上传到服务器的路径--:"+path);
        }
        sftpConfig = new SftpDTO(host,port,userName,password,timeout,path);
        // 连接sftp
        ChannelSftp sftp = sftpUtil.connect(sftpConfig);

        if (file.size() != 0 && type != null) {
            for (MultipartFile multipartFile : file) {
                //获取文件名称
                String filename = multipartFile.getOriginalFilename();
                if (StringUtils.isNotBlank(filename)) {
                    filename = filename.replace(" ", "");
                    // 获取文件名
                    String fileName = filename.substring(0, filename.length() - 4);
                    String titleFilePaths = null;
                    SysAudios sysAudios = null;
                    SysVideos sysVideos = null;
                    // 1: 音频 2:视频
                    if (type == 1) {
                        // 存库音频全路径
                        titleFilePaths = titleAudiosPath + format + "/" + filename;
                        sysAudios = new SysAudios();
                        sysAudios.setAudioName(fileName);
                        sysAudios.setAudioPath(titleFilePaths);
                        sysAudios.setCreateBy(createName);
                        sysAudiosList.add(sysAudios);

                        sftpUtil.uploadList(multipartFile, sftpConfig.getRemoteRootPath(), sftp, filename);
                    } else {
                        // 存库视频全路径
                        titleFilePaths = titleVideosPath + format + "/" + filename;
                        sysVideos = new SysVideos();
                        sysVideos.setVideoName(fileName);
                        sysVideos.setVideoPath(titleFilePaths);
                        sysVideos.setCreateBy(createName);
                        sysVideosList.add(sysVideos);

                        sftpUtil.uploadList(multipartFile, sftpConfig.getRemoteRootPath(), sftp, filename);
                    }
                    log.info(type == 1 ? "音频" : "视频" +"——"+"文件上传-存库路径---:"+titleFilePaths);
                }
            }

            // 断开sftp连接
            sftpUtil.disConnect(sftp);
            // 储存数据
            if (sysAudiosList != null && sysAudiosList.size() != 0) {
                sysAudiosService.saveAudioInfo(sysAudiosList);
                log.info("音频信息入库成功");
            }
            if (sysVideosList != null && sysVideosList.size() != 0) {
                sysVideosService.saveVideoInfo(sysVideosList);
                log.info("视频信息入库成功");
            }
        }
        return ResponseResult.create().success(true).data(200);
    }
}

希望对你有所帮助!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值