Springboot通过SFTP上传文件到服务器

时间:2025-03-11 06:57:13

流程是这样的:

前端选择文件上传-------->调用后台接口,后台连接服务器(Linux)--------->上传成功

 前端无论是通过ajax,还是form表单直接提交都可以,这里暂时以form方式提交 这里需要依靠一个Sftps的工具类


先导入依赖

<dependency>
	<groupId></groupId>
	<artifactId>jsch</artifactId>
	<version>0.1.54</version>
</dependency>

public final class Sftps {

    private static final Logger log = ();

    private Session sshSession;

    private ChannelSftp sftp;

    /**
     * 连接sftp服务器
     * @param host
     * @param port
     * @param username
     * @param password
     * @return
     * @throws Exception
     */
    public ChannelSftp connect(String host, int port, String username, String password) throws Exception {
        JSch jsch = new JSch();
        sshSession = (username, host, port);

        ("Session created.");

        (password);
        Properties sshConfig = new Properties();
        ("StrictHostKeyChecking", "no");
        (sshConfig);
        ();

        ("Session connected.");
        ("Opening Channel.");

        Channel channel = ("sftp");
        ();
        sftp = (ChannelSftp) channel;

        ("Connected to " + host + ".");

        return sftp;
    }
    /**
     * 连接sftp服务器
     * @param host
     * @param port
     * @param username
     * @param privateKey
     * @param passphrase
     * @return
     * @throws Exception
     */
    public ChannelSftp connect(String host, int port, String username, String privateKey ,String passphrase) throws Exception {
        JSch jsch = new JSch();

        //设置密钥和密码
        if (!(privateKey)) {
            if (!(passphrase)) {
                //设置带口令的密钥
                (privateKey, passphrase);
            } else {
                //设置不带口令的密钥
                (privateKey);
            }
        }
        sshSession = (username, host, port);

        ("Session created.");

        Properties sshConfig = new Properties();
        ("StrictHostKeyChecking", "no");
        (sshConfig);
        ();

        ("Session connected.");
        ("Opening Channel.");

        Channel channel = ("sftp");
        ();
        sftp = (ChannelSftp) channel;

        ("Connected to " + host + ".");

        return sftp;
    }

    public void portForwardingL(int lport, String rhost, int rport) throws Exception {
        int assinged_port = (lport, rhost, rport);
        ("localhost:"+assinged_port+" -> "+rhost+":"+rport);
    }
    /**
     * 断开连接
     */
    public void disconnect() {
        if (sftp != null) ();
        if (sshSession != null) ();
    }
    /**
     * 上传文件
     *
     * @param directory
     *            上传的目录
     * @param uploadFile
     *            要上传的文件
     * @param sftp
     */
    public void upload(String directory, String uploadFile) throws Exception {
        (directory);
        File file = new File(uploadFile);
        (new FileInputStream(file), ());
    }

    public void upload(String directory, File file) throws Exception {
        (directory);
        (new FileInputStream(file), ());
        ("upload file "+() + " to host " + ());
    }
    //利用流上传文件 fileName
    public void uploadfileInputStream(MultipartFile file, String directory, String fileName) throws Exception {
        (directory);
        ((),fileName);
    }
    public void uploadDir(File src, String dst) throws Exception{
        if (!exist(dst)) {
            (dst);
        }
        if (()) {
            upload(dst, src);
        } else {
            for (File file : ()) {
                if (()) {
                    uploadDir(file, dst + "/" + ());
                }
                upload(dst, file);
            }
        }
    }
    /**
     * 目录是否查找
     * @param path
     * @return
     * @throws SftpException
     */
    public boolean exist(String path) throws SftpException {
        String pwd = ();
        try {
            (path);
        } catch (SftpException e) {
            if ( == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
                return false;
            } else {
                throw e;
            }
        } finally {
            (pwd);
        }

        return true;
    }
    /**
     * 下载文件
     * @param directory
     * @param downloadFile
     * @param saveFile
     * @throws Exception
     */
    public void download(String directory, String downloadFile, String saveFile) throws Exception {
        (directory);
        File file = new File(saveFile);
        (downloadFile, new FileOutputStream(file));
    }

    /**
     * 下载文件
     * @param directory
     * @param downloadFile
     * @param saveFile
     * @throws Exception
     */
    public void download(String directory, String downloadFile, File saveFile) throws Exception {
        (directory);
        (downloadFile, new FileOutputStream(saveFile));
        ("download file "+directory + "/" +downloadFile + " from host " + ());
    }

    /**
     * 下载文件
     * @param src
     * @param dst
     * @throws Exception
     */
    @SuppressWarnings("unchecked")
    public void downloadDir(String src, File dst) throws Exception {
        try {
            (src);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            ();
        }

        ();

        Vector<LsEntry> files = (src);
        for (LsEntry lsEntry : files) {
            if (().equals(".") || ().equals("..")) {
                continue;
            }
            if (().startsWith("d")) {
                downloadDir(src + "/" + (), new File(dst, ()));
            } else {
                download(src, (), new File(dst, ()));
            }

        }
    }

    /**
     *  删除文件
     * @param directory
     * @param deleteFile
     * @throws SftpException
     */
    public void delete(String directory, String deleteFile) throws SftpException {
        (directory);
        (deleteFile);
    }

    /**
     * 列出目录下的文件
     * @param directory
     * @return
     * @throws SftpException
     */
    public Vector listFiles(String directory) throws SftpException {
        return (directory);
    }

    public Session getSshSession() {
        return sshSession;
    }
    public ChannelSftp getSftp() {
        return sftp;
    }
}

在这个工具类里,我自己在这个类的基础之上往里面加了一个方法,利用流上传文件

//利用流上传文件 fileName
    public void uploadfileInputStream(MultipartFile file, String directory, String fileName) throws Exception {
        (directory);
        ((),fileName);
    }

这里要注意的是form表单中一定要添加 enctype="multipart/form-data"不然在后台接收不到文件流

<form class="form-horizontal" action="/upload" name="upload"  method="post" enctype="multipart/form-data">
        <input type="file" name="filename" /><br/>
        <input type="submit" value="提交" /><br/>
</form>

 后端Controller

@RequestMapping("/upload")
    public String uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("fileName") String fileName) throws Exception {
        if(()||()){
            new Exception("未接收到指定参数");
            return "";
        }else{
            SftpsEntity sftpsAll = ();
            try {
                sftps = new Sftps();
                //连接服务器
                ("192.168.1.154", 22,"root","123456");
                //上传到服务器的位置
                (file, "/", fileName);
            } catch (Exception e) {
                ();
            } finally {
                ();
            }
            return "{message:\"上传成功\"}";
        }

 uploadfileInputStream()三个参数分别代表

file 文件流(文件),

/  代表存在服务器的根目录下,

fileName 文件全名称,包括后缀,三者缺一不可!