随笔 - 3  文章 - 0  评论 - 0  阅读 - 161

SFTP协议实现远程服务器文件的上传和下载

本文通过SFTP的方式实现服务器文件的上传和下载

1.导入项目依赖

点击查看代码
 <dependency>
            <groupId>com.jcraft</groupId>
            <artifactId>jsch</artifactId>
            <version>0.1.55</version>
        </dependency>
2.创建一个访问文件服务器的工具类 配置信息取自配置文件
点击查看代码
#sftp
sftp.host=172.17.10.20
sftp.username=root
sftp.password=Huangshi198588!0.
sftp.port=22
sftp.remotePath=/data/prod/upload/ims-cust/fileUpload
3.创建一个工具类
点击查看代码

package com.pangus.ims.custom.server.lannray.util;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

@Component
public class LannraySFTPUtil {

    @Value("${sftp.host}")
    private String host;

    @Value("${sftp.username}")
    private String username;

    @Value("${sftp.password}")
    private String password;

    @Value("${sftp.port}")
    private int port;

    @Value("${sftp.remotePath}")
    private String remotePath;

    private static final int SSH_FX_FILE_ALREADY_EXISTS = 4; // 定义常量

    public void downloadFile(String remoteFilePath,OutputStream outputStream) throws JSchException, SftpException, IOException {
        JSch jsch = new JSch();
        Session session = jsch.getSession(username, host, port);
        session.setPassword(password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();
        ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
        channel.connect();
        try (InputStream inputStream = channel.get(remoteFilePath)) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
        }
        channel.disconnect();
        session.disconnect();
    }

    public String   uploadFile(String base64Data, String devCode, String fileName) throws Exception {

        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        // 将 Date 对象格式化为字符串
        String dateStr = dateFormat.format(now);
        // 解码 Base64 字符串
        byte[] fileData = Base64.getDecoder().decode(base64Data);
        String finalRemotePath=remotePath+"/"+devCode+"/"+dateStr;
        JSch jsch = new JSch();
        Session session = null;
        try {
            // 连接到远程服务器
            session = jsch.getSession(username, host, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();
            // 创建 SFTP 通道
            ChannelSftp sftpChannel = (ChannelSftp) session.openChannel("sftp");
            sftpChannel.connect();
            // 检查并创建目录
            createRemoteDirectory(sftpChannel, finalRemotePath);
            String filePath=finalRemotePath+"/"+fileName;
            // 将文件上传
            try (ByteArrayInputStream inputStream = new ByteArrayInputStream(fileData)) {
                sftpChannel.put(inputStream, filePath);
                System.out.println("文件已成功上传到远程服务器: " + filePath);
                return filePath;
            } catch (IOException e) {
                throw new IOException("文件上传失败", e);
            } finally {
                sftpChannel.disconnect();
            }

        } catch (Exception e) {
            throw new Exception("SFTP 上传失败", e);
        } finally {
            if (session != null && session.isConnected()) {
                session.disconnect();
            }
        }
    }



    private void createRemoteDirectory(ChannelSftp sftpChannel, String remoteDir) throws SftpException {
        String[] pathParts = remoteDir.split("/");
        StringBuilder currentPath = new StringBuilder();

        for (String part : pathParts) {
            if (!part.isEmpty()) {
                currentPath.append("/").append(part);
                try {
                    sftpChannel.mkdir(currentPath.toString());
                } catch (SftpException e) {
                    // 检查我们定义的常量
                    if (e.id != SSH_FX_FILE_ALREADY_EXISTS) {
                        throw e; // 如果不是“已经存在”的错误,则重新抛出
                    }
                }
            }
        }
    }
}


4.实现文件的下载
点击查看代码
 public DataRow downloadRomate(DataTable dataTable) throws JSchException, SftpException, IOException {
        if (dataTable.isEmpty()) {
            // SYS0102:数据为空,无任何数据可操作。
            throw new SystemException(messageHelper.get("common.no.data.operator"));
        }
        List<DataRowImpl> rows = dataTable.getRows();
        //文件名
        String fileName=rows.get(0).getString("file_name");
        //文件路径
        String filePath=rows.get(0).getString("file_path");
        //从文件服务器下载文件返回前端
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        lannraySFTPUtil.downloadFile(filePath,outputStream);
        String base64EncodedString = Base64.getEncoder().encodeToString(outputStream.toByteArray());

        // 创建返回数据
        DataRow rowReturn = DataRowImpl.create()
                .setString( "file_name", fileName)
                .setString("file_path" , filePath)
                .setString("file_data" , base64EncodedString);

        return rowReturn;
    }
5.前端接收到后端下载的数据 实现下载
点击查看代码
	// 下载按钮事件请求
   const downloadBtnClick = async function (formData) {
		
		const dsTestFile = new DataTable({
			rows: [],
			columns: lannrayFhmDataModel.columns,
			keyColumns: lannrayFhmDataModel.keyColumns,
			modelCode: lannrayFhmDataModel.modelCode,
			menuCode: _this.getMenuCode(),
		})
			const row = {}
			row['file_name'] = formData['file_name']
			row['file_path'] = formData['file_path']
		
			dsTestFile.rows.push(row)
		await server.excuteParams(lannrayFhmDataModel.prefixUrl + '/downloadRomate', dsTestFile).then(res => {
		  try {
			
			// 处理返回信息,成功信息,报错信息等
			// appUtils.messageAlert(res)
			//后端返回的文件服务器文件Base64加密数据
			const fileName = res.value.file_name;
			const fileData = res.value.file_data;
			
			console.log(fileName);
			const byteCharacters = atob(fileData);
			const byteNumbers = new Array(byteCharacters.length);
			for (let i = 0; i < byteCharacters.length; i++) {
				byteNumbers[i] = byteCharacters.charCodeAt(i);
			}
			const byteArray = new Uint8Array(byteNumbers);
			const blob = new Blob([byteArray], { type: 'application/octet-stream' });
			// 创建下载链接并触发下载
			const downloadLink = document.createElement('a');
			downloadLink.href = URL.createObjectURL(blob);
			downloadLink.download = fileName;
			document.body.appendChild(downloadLink);
			downloadLink.click();
			document.body.removeChild(downloadLink); 
	
		  } catch (error) {
			console.error('文件下载失败:', error);
		  }
		
		})	
	}
6.实现文件上传 fileData 为文件字节base64加密转字符串
点击查看代码
SFTPUtils sftpUtils = new SFTPUtils(configFilePath);
  savaPath= sftpUtils.uploadFile(fileData,devCode,fileName);
posted on   呆呆小帅哥  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示