java使用jcraft SFTP上传到服务器上

发布时间 2023-08-09 20:33:47作者: Rzk

前言

因为两台服务器,有一台是用于前端项目,有一台用于其他项目,其他项目的这台服务器要读取二维码,就想这在前端项目上传图片然后后端项目将项目上传到另一台服务器的指定目录上

后端服务

引入依赖

需要引入maven依赖

		<jcraft.version>0.1.54</jcraft.version>
		<!--sftp文件上传-->
		<dependency>
			<groupId>com.jcraft</groupId>
			<artifactId>jsch</artifactId>
			<version>${jcraft.version}</version>
		</dependency>

application.yml配置

# 上传其他服务器操作
sftp:
  # 端口
  port: 22
  # 用户名
  user: root
  # 密码
  password:  xxxx.xxxx.xxxx
  # ip
  ip: xxxx.xxxx.xxxx
  # 服务器保存路径
  filePath: /home/

工具类

操作文件


import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

@Component
public class SftpUploadImage {


    //服务器端口号
    @Value(value = "${sftp.port}")
    private int sftpPort;
    //服务器用户名
    @Value(value = "${sftp.user}")
    private String sftpUser;
    //服务器密码
    @Value(value = "${sftp.password}")
    private String sftpPassword;
    //服务器ip
    @Value(value = "${sftp.ip}")
    private String sftpIp;
    //服务器保存路径
    @Value(value = "${sftp.filePath}")
    private String sftpFilePath;


    /**
     * 利用JSch包实现SFTP上传文件
     *
     * @param bytes    文件字节流
     * @param fileName 文件名
     * @throws Exception
     */
    public void sshSftp(byte[] bytes, String fileName) throws Exception {


        Session session = null;
        Channel channel = null;

        JSch jSch = new JSch();

        if (sftpPort <= 0) {
            //连接服务器,采用默认端口
            session = jSch.getSession(sftpUser, sftpIp);
        } else {
            //采用指定的端口连接服务器
            session = jSch.getSession(sftpUser, sftpIp, sftpPort);
        }

        //如果服务器连接不上,则抛出异常
        if (session == null) {
            throw new Exception("session is null");
        }

        //设置登陆主机的密码
        session.setPassword(sftpPassword);//设置密码
        //设置第一次登陆的时候提示,可选值:(ask | yes | no)
        session.setConfig("userauth.gssapi-with-mic", "no");
        session.setConfig("StrictHostKeyChecking", "no");
        //设置登陆超时时间
        session.connect(30000);

        OutputStream outstream = null;
        try {
            //创建sftp通信通道
            channel = (Channel) session.openChannel("sftp");
            channel.connect(1000);
            ChannelSftp sftp = (ChannelSftp) channel;


            //进入服务器指定的文件夹
            sftp.cd(sftpFilePath);

            //以下代码实现从本地上传一个文件到服务器,如果要实现下载,对换一下流就可以了
            outstream = sftp.put(fileName);
            outstream.write(bytes);

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关流操作
            if (outstream != null) {
                outstream.flush();
                outstream.close();
            }
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
            System.out.println("上传成功!");
        }
    }

    /**
     * 利用JSch包实现SFTP查询文件列表
     *
     * @return 文件列表
     * @throws Exception
     */
    public Vector<ChannelSftp.LsEntry> getSftpFileList() throws Exception {
        Session session = null;
        Channel channel = null;

        JSch jSch = new JSch();

        if (sftpPort <= 0) {
            // 连接服务器,采用默认端口
            session = jSch.getSession(sftpUser, sftpIp);
        } else {
            // 采用指定的端口连接服务器
            session = jSch.getSession(sftpUser, sftpIp, sftpPort);
        }

        // 如果服务器连接不上,则抛出异常
        if (session == null) {
            throw new Exception("session is null");
        }

        // 设置登陆主机的密码
        session.setPassword(sftpPassword);// 设置密码
        // 设置第一次登陆的时候提示,可选值:(ask | yes | no)
        session.setConfig("userauth.gssapi-with-mic", "no");
        session.setConfig("StrictHostKeyChecking", "no");
        // 设置登陆超时时间
        session.connect(30000);

        Vector<ChannelSftp.LsEntry> fileList = null;
        try {
            // 创建sftp通信通道
            channel = (Channel) session.openChannel("sftp");
            channel.connect(1000);
            ChannelSftp sftp = (ChannelSftp) channel;

            // 进入服务器指定的文件夹
            sftp.cd(sftpFilePath);

            // 获取文件列表
            fileList = sftp.ls("*");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
        }

        return fileList;
    }


    /**
     * 从SFTP服务器下载文件
     *
     * @param fileName 文件名
     * @return 下载的文件内容
     * @throws Exception
     */
    public byte[] downloadFileContent(String fileName) throws Exception {
        Session session = null;
        Channel channel = null;

        JSch jSch = new JSch();

        if (sftpPort <= 0) {
            // 连接服务器,采用默认端口
            session = jSch.getSession(sftpUser, sftpIp);
        } else {
            // 采用指定的端口连接服务器
            session = jSch.getSession(sftpUser, sftpIp, sftpPort);
        }

        // 设置登陆主机的密码
        session.setPassword(sftpPassword);// 设置密码
        // 设置第一次登陆的时候提示,可选值:(ask | yes | no)
        session.setConfig("userauth.gssapi-with-mic", "no");
        session.setConfig("StrictHostKeyChecking", "no");
        // 设置登陆超时时间
        session.connect(30000);

        byte[] fileContent = null;
        try {
            // 创建sftp通信通道
            channel = session.openChannel("sftp");
            channel.connect(1000);
            ChannelSftp sftp = (ChannelSftp) channel;

            // 进入服务器指定的文件夹
            sftp.cd(sftpFilePath);

            // 下载文件
            InputStream inputStream = sftp.get(fileName);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, bytesRead);
            }

            fileContent = outputStream.toByteArray();

            outputStream.close();
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
        }

        return fileContent;
    }

    /**
     * 获取文件类型对应的媒体类型
     *
     * @param fileName 文件名
     * @return 媒体类型
     */
    public MediaType getMediaType(String fileName) {
        String extension = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
        MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM;

        Map<String, MediaType> mediaTypeMap = new HashMap<>();
        mediaTypeMap.put("jpg", MediaType.IMAGE_JPEG);
        mediaTypeMap.put("jpeg", MediaType.IMAGE_JPEG);
        mediaTypeMap.put("png", MediaType.IMAGE_PNG);
        mediaTypeMap.put("gif", MediaType.IMAGE_GIF);
        mediaTypeMap.put("bmp", MediaType.parseMediaType("image/bmp"));
        mediaTypeMap.put("txt", MediaType.TEXT_PLAIN);
        mediaTypeMap.put("php", MediaType.TEXT_PLAIN);
        mediaTypeMap.put("zip", MediaType.parseMediaType("application/zip"));
        mediaTypeMap.put("tar.gz", MediaType.parseMediaType("application/gzip"));

        if (mediaTypeMap.containsKey(extension)) {
            mediaType = mediaTypeMap.get(extension);
        }

        return mediaType;
    }

    public boolean deleteFilesInDirectory(String directory) {
        Session session = null;
        Channel channel = null;
        try {


            JSch jSch = new JSch();

            if (sftpPort <= 0) {
                //连接服务器,采用默认端口
                session = jSch.getSession(sftpUser, sftpIp);
            } else {
                //采用指定的端口连接服务器
                session = jSch.getSession(sftpUser, sftpIp, sftpPort);
            }

            //如果服务器连接不上,则抛出异常
            if (session == null) {
                throw new Exception("session is null");
            }

            //设置登陆主机的密码
            session.setPassword(sftpPassword);//设置密码
            //设置第一次登陆的时候提示,可选值:(ask | yes | no)
            session.setConfig("userauth.gssapi-with-mic", "no");
            session.setConfig("StrictHostKeyChecking", "no");
            //设置登陆超时时间
            session.connect(30000);


            // 创建sftp通信通道
            channel = session.openChannel("sftp");
            channel.connect(1000);
            ChannelSftp sftp = (ChannelSftp) channel;

            // 进入服务器指定的文件夹
            sftp.cd(sftpFilePath);


            // 获取目录下的文件列表
            Vector<ChannelSftp.LsEntry> files = sftp.ls(".");
            for (ChannelSftp.LsEntry file : files) {
                if (!file.getAttrs().isDir()) {
                    // 删除文件
                    sftp.rm(file.getFilename());
                }
            }

            // 断开SFTP连接
            // ...


            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (session != null) {
                session.disconnect();
            }
            if (channel != null) {
                channel.disconnect();
            }
        }

    }


}


后端接口


@RestController
@RequestMapping("/wx/groupchat/")
public class WxUploadImgController {
    private Logger logger = LoggerFactory.getLogger(WxUploadImgController.class);


    @Resource
    SftpUploadImage sftpUploadImage;

    /**
     * 处理文件上传
     * @param file
     * @return
     */
    @RequestMapping(value="uploadimg", method = RequestMethod.POST)
    @RequiresPermissions("wx:groupchat:uploadimg")
    public @ResponseBody String uploadImg(@RequestParam("file") MultipartFile file) {
        logger.info("进入处理文件上传接口");
        try {
            //MultipartFile转file
            FileUtil fileUtil = new FileUtil();
            File m2F = fileUtil.M2F(file);
            FileInputStream fileInputStream = new FileInputStream(m2F);
            BufferedInputStream in = new BufferedInputStream(fileInputStream);
            ByteArrayOutputStream out = new ByteArrayOutputStream(1024);

            byte[] temp = new byte[1024];
            int size = 0;
            while ((size = in.read(temp)) != -1) {
                out.write(temp, 0, size);
            }
            in.close();
            byte[] content = out.toByteArray();
            //这里具体文件命名可以改成获取当前文件名字再做修改
            sftpUploadImage.sshSftp(content, "rzk"+".jpg");

            return "上传成功";
        } catch (Exception e) {
            return "上传失败";
        }
    }


    /**
     * 获取文件列表
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("分页")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "当前页码,从1开始", paramType = "query", required = true, dataType="int") ,
            @ApiImplicitParam(value = "每页显示记录数", paramType = "query",required = true, dataType="int") ,
            @ApiImplicitParam(value = "排序字段", paramType = "query", dataType="String") ,
            @ApiImplicitParam( value = "排序方式,可选值(asc、desc)", paramType = "query", dataType="String")
    })
    @RequiresPermissions("wx:groupchat:list")
    public R list() {
        try {
            Vector<ChannelSftp.LsEntry> fileList = sftpUploadImage.getSftpFileList();
            List<String> filenames = new ArrayList<>();
            for (ChannelSftp.LsEntry entry : fileList) {
                if (!entry.getAttrs().isDir()) {
                    filenames.add(entry.getFilename());
                }
            }
            return R.ok().put("page", filenames);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

    }

    /**
     * 获取文件内容  预览
     * @param filename
     * @return
     */
    @GetMapping("/preview/{filename}")
    @RequiresPermissions("wx:groupchat:preview")
    public ResponseEntity<byte[]> previewFile(@PathVariable("filename") String filename) {
        try {
            byte[] fileContent = sftpUploadImage.downloadFileContent(filename);
            if (fileContent != null) {
                MediaType mediaType = sftpUploadImage.getMediaType(filename);

                HttpHeaders headers = new HttpHeaders();
                headers.setContentDispositionFormData("attachment", filename);
                headers.setContentType(mediaType);

                return new ResponseEntity<>(fileContent, headers, HttpStatus.OK);
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * 删除文件
     * @param directory
     * @return
     */
    @DeleteMapping("/delete")
    @RequiresPermissions("wx:groupchat:delete")
    public ResponseEntity<String> deleteFiles(@RequestParam("directory") String directory) {
        try {
            boolean deleted = sftpUploadImage.deleteFilesInDirectory(directory);
            if (deleted) {
                return ResponseEntity.ok("Files deleted successfully");
            } else {
                return ResponseEntity.notFound().build();
            }
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }
}