Java使用流下载SFTP上文件,压缩输出到客户端中

219 阅读2分钟

SFTP连接使用的依赖

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

由于有下载SFTP文件需求,但文件为CSV,文件太大。所以看看能不能对流数据进行压缩输出下载。

源文件大小约为600MB。

查询资料Java连接SFTP方式如下

try {
    JSch jsch = new JSch();

    Session session = jsch.getSession("root", "192.168.192.188", 22);
    session.setPassword("u8PZSQz7YCRsJKwyV2vt5nQS");
    Properties config = new Properties();
    config.put("StrictHostKeyChecking", "no");

    session.setConfig(config);
    //打开了,记得要关闭
    session.connect();

    Channel channel = session.openChannel("sftp");
    channel.connect();

    //当前方式是sftp,所以,对应会话的类为ChannelSftp,进行强转即可
    ChannelSftp  sftp = (ChannelSftp) channel;
}catch (Exception e){
    e.printStackTrace();
    System.out.println("error" + e.getMessage());
}

阅读 ChannelSftp类发现有个方法

可以将下载流进行输出

public void get(String src, OutputStream dst) throws SftpException{
  get(src, dst, null, OVERWRITE, 0);
}

那么思考下,想到以下需求

要求:

1、不需要将文件下载到服务器本地,直接操作sftp下载的流进行压缩操作

2、直接将流压缩后输出到浏览器并进行下载。

最终实现DEMO

/**
 *
 * 下载sftp文件,并压缩流输出到浏览器下载
 * @param response res
 * @param dic 目录
 * @param fileName 文件名称
 */
@RequestMapping("/downloadSftpFile")
public void downloadSftpFile(HttpServletResponse response,String dic, String fileName) {

    ServletOutputStream outputStream = null;
    ZipOutputStream zos = null;
    try {
        JSch jsch = new JSch();
        Session session = jsch.getSession("root", "192.168.0.2", 22);
        session.setPassword("test");
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");

        session.setConfig(config);
        session.connect();
        //打开了,记得要关闭
        Channel channel = session.openChannel("sftp");
        channel.connect();
        //当前方式是 sftp,所以,对应会话的类为ChannelSftp,进行强转即可
        ChannelSftp sftp = (ChannelSftp) channel;
        response.setContentType("application/octet-stream");

        //重命名,浏览器下载文件名称
        response.setHeader("Content-Disposition", "attachment;filename="
                + URLEncoder.encode(fileName.replace(".csv", ".zip"), "UTF-8"));
        sftp.cd(dic);
        //获取输出流
        outputStream = response.getOutputStream();
        //创建zip压缩流
        zos = new ZipOutputStream(outputStream);
        // 创建一个新的ZIP条目,这将是被压缩的条目名
        ZipEntry entry = new ZipEntry(fileName);
        zos.putNextEntry(entry);
        //将流输出到zos中,经过zos后,会将数据压缩,输出到outputStream
        sftp.get(fileName, zos);
        //记得关闭,否则下载后无法进行解压
        zos.closeEntry();
        zos.close();
        //关闭sftp连接
        sftp.disconnect();
    } catch (Exception e) {
        e.printStackTrace();
        System.out.println("error" + e.getMessage());
        if (outputStream != null) {
            try {
                outputStream.close();
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }
        }
    }


}

结果: 600M文件,压缩后只有100M多了。压缩了接近六倍多。