Downloading file from SFTP directly to HTTP response without using intermediate file

半城伤御伤魂 提交于 2019-12-08 04:08:54

问题


I am trying to download a file through SFTP using Java JSsch library. I am successful in downloading the file to a local directory. **But, all I need is to download the file directly to browser without giving any local destination path (like how file gets downloaded in Chrome). I am using Spring controller AngularJS Promise to catch the response. Below is my code.

@RequestMapping(value = "/downloadAttachment", method = RequestMethod.POST,
                produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
public void downloadAttachment(
        @RequestParam(value = "fileName") String fileName,
        @RequestParam(value = "filePath") String filePath,
        @RequestParam(value = "fileId") String fileId,
        HttpServletResponse response, Locale locale) throws Exception {
    InputStream is = null;
    if(!fileName.isEmpty() && !filePath.isEmpty() && !fileId.isEmpty()){
        String directory = filePath;
        java.util.Properties config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        JSch ssh = new JSch();
        Session session = ssh.getSession(sftpLogin, sftpAddress, 22);
        session.setConfig(config);
        session.setPassword(sftpPassword);
        session.connect();
        logger.info("Connection to server established");
        Channel channel = session.openChannel("sftp");
        channel.connect();

        ChannelSftp sftp = (ChannelSftp) channel;
        sftp.cd(directory);
        is = sftp.get(fileName);
        channel.disconnect();
        session.disconnect();
    }
    IOUtils.copy(is, response.getOutputStream());
    is.close();
    response.getOutputStream().close();
    response.flushBuffer();
}

I don't know the type of file to be downloaded. So, I used MediaType.APPLICATION_OCTET_STREAM_VALUE. This is giving me Exception which is given below.

java.io.IOException: Pipe closed java.io.PipedInputStream.read(Unknown Source) java.io.PipedInputStream.read(Unknown Source) com.jcraft.jsch.ChannelSftp.fill(ChannelSftp.java:2909) com.jcraft.jsch.ChannelSftp.header(ChannelSftp.java:2935) com.jcraft.jsch.ChannelSftp.access$500(ChannelSftp.java:36) com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1417) com.jcraft.jsch.ChannelSftp$2.read(ChannelSftp.java:1364) org.apache.commons.io.IOUtils.copyLarge(IOUtils.java:1025) org.apache.commons.io.IOUtils.copy(IOUtils.java:999)


回答1:


You are disconnecting channel and session before actually reading anything from input stream (stored in variable "is"). Please call following lines after IOUtils.copy() instead of before -

is.close();
channel.disconnect();
session.disconnect();

You can also try directly calling

sftp.get(filename, response.getOutputSteam());

Have a look at documentation here




回答2:


You cannot close the SFTP session before you try to read the data.

This is the correct code:

is = sftp.get(fileName);
IOUtils.copy(is, response.getOutputStream());
channel.disconnect();
session.disconnect();
is.close();


来源:https://stackoverflow.com/questions/44842194/downloading-file-from-sftp-directly-to-http-response-without-using-intermediate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!