【SFTP】使用Jsch进行跨服务器传输图片、文件

1.需求背景:跨服务器,将图片上传到新的服务器(图片服务器)保存

a.使用sftp的时候,经常报错ssh连接不对,换了jsch的jar进行开发、ftp工具类

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader;
import java.io.OutputStream; 
import java.util.Properties;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
 
/** 
 * FTP服务器工具类 
 * 
 */ 
public class FTPUtils { 
	    public static final String CHANNELTYPE_SFTP="sftp";
	    public static final String CHANNELTYPE_EXEC="exec";
	    private Session session;//会话
	    private Channel channel;//连接通道
	    private ChannelSftp sftp;// sftp操作类
	    private JSch jsch;
	    /*protected static String host=getLinuxParam()[0];
	    protected static String port=getLinuxParam()[1];
	    protected static String user=getLinuxParam()[2];
	    protected static String password=getLinuxParam()[3];*/
	    /*protected static String host="120.27.167.70";
	    protected static String port="6331";
	    protected static String user="ytyfemall";
	    protected static String password="ytyfemall";*/
	    protected static String host=ConfigManager.getString("file.host", "");;
	    protected static String port=ConfigManager.getString("file.port", "");;
	    protected static String user=ConfigManager.getString("file.user", "");;
	    protected static String password=ConfigManager.getString("file.password", "");;

	    private static String[] getLinuxParam(){
	        Properties props=new Properties();//读取文件类型创建对象。
	        try {
	            ClassLoader classLoader = FTPUtils.class.getClassLoader();// 读取属性文件
	            InputStream in = classLoader.getResourceAsStream("c");
	            props.load(in); /// 加载属性列表
	            if(in!=null){
	                in.close();
	            }
	        } catch (Exception e) {
	            System.out.println("Linux连接参数异常:"+e.getMessage());
	        }
	        String[] str={"","","",""};
	        str[0]=props.getProperty("file.host");
	        str[1]=props.getProperty("file.port");
	        str[2]=props.getProperty("file.user");
	        str[3]=props.getProperty("file.password");
	        return str;
	    }
	    /**
	     * 断开连接
	     */
	    public static void closeConnect(Session session, Channel channel, ChannelSftp sftp){
	        if (null != sftp) {
	            sftp.disconnect();
	            sftp.exit();
	            sftp = null;
	        }
	        if (null != channel) {
	            channel.disconnect();
	            channel = null;
	        }
	        if (null != session) {
	            session.disconnect();
	            session = null;
	        }
	        System.out.println("连接已关闭");
	    }

	    /**
	     * 连接ftp/sftp服务器
	     *
	     * @param sftpUtil 类
	     */
	    public static void getConnect(FTPUtils sftpUtil,String openChannelType) throws Exception {
	        Session session = null;
	        Channel channel = null;

	        JSch jsch = new JSch();
	        session = jsch.getSession(user, host, Integer.parseInt(port));
	        session.setPassword(password);
	        // 设置第一次登陆的时候提示,可选值:(ask | yes | no)
	        // 不验证 HostKey
	        session.setConfig("StrictHostKeyChecking", "no");
	        try {
	            session.connect();
	        } catch (Exception e) {
	            if (session.isConnected())
	                session.disconnect();
	            System.out.println("连接服务器失败");
	        }
	        channel = session.openChannel(openChannelType);
	        try {
	            channel.connect();
	        } catch (Exception e) {
	            if (channel.isConnected())
	                channel.disconnect();
	            System.out.println("连接服务器失败");
	        }
	        sftpUtil.setJsch(jsch);
	        if(openChannelType.equals(CHANNELTYPE_SFTP)){
	            sftpUtil.setSftp((ChannelSftp) channel);
	        }
	        sftpUtil.setChannel(channel);
	        sftpUtil.setSession(session);

	    }


	    /**
	     * 上传文件
	     *
	     * @param directory  上传的目录-相对于SFPT设置的用户访问目录
	     * @param uploadFile 要上传的文件全路径
	     */
	    public static boolean upload(String directory, String uploadFile, String fileName) {
	        boolean resultState=false;
	        FTPUtils sftpUtil = new FTPUtils();
	        try{
	            getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
	            Session session = sftpUtil.getSession();
	            Channel channel = sftpUtil.getChannel();
	            ChannelSftp sftp = sftpUtil.getSftp();// sftp操作类
	            try {
	                sftp.cd(directory); //进入目录
	            } catch (SftpException sException) {
	                if (ChannelSftp.SSH_FX_NO_SUCH_FILE == sException.id) { //指定上传路径不存在
	                    sftp.mkdir(directory);//创建目录
	                    sftp.cd(directory);  //进入目录
	                }
	            }
	            File file = new File(uploadFile);
	            InputStream in = new FileInputStream(file);
	            sftp.put(in, fileName);
	            in.close();
	            closeConnect(session, channel, sftp);
	            resultState=true;
	        }catch (Exception e){
	            System.out.println("上传文件异常");
	        }
	        return resultState;
	    }

	    /**
	     * 获取已连接的Sftp
	     * @return SftpUtil
	     */
	    public static FTPUtils getConnectSftp(){
	    	FTPUtils sftpUtil=new FTPUtils();
	        try {
	            getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
	          return sftpUtil;
	        }catch (Exception e){
	            System.out.println("下载文件异常");
	        }
	        return null;
	    }

	    /**
	     * 删除文件
	     * @param directory 要删除文件所在目录
	     * @param deleteFile 要删除的文件
	     */
	    public static boolean delete(String directory, String deleteFile){
	        boolean resultState=false;
	        FTPUtils sftpUtil=new FTPUtils();
	        try {
	            getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
	            Session session = sftpUtil.getSession();
	            Channel channel = sftpUtil.getChannel();
	            ChannelSftp sftp = sftpUtil.getSftp();// sftp操作类
	            sftp.cd(directory); //进入的目录应该是要删除的目录的上一级
	            sftp.rm(deleteFile);//删除目录
	            closeConnect(session,channel,sftp);
	            resultState=true;
	        }catch (Exception e){
	            System.out.println("删除文件异常");
	        }
	        return resultState;
	    }

	    /**
	     JSch有三种文件传输模式:
	     (1)OVERWRITE:完全覆盖模式。JSch的默认文件传输模式,传输的文件将覆盖目标文件。
	     (2)APPEND:追加模式。如果目标文件已存在,则在目标文件后追加。
	     (3)RESUME:恢复模式。如果文件正在传输时,由于网络等原因导致传输中断,则下一次传输相同的文件
	     时,会从上一次中断的地方续传。
	     */
	    /**
	     * 追加文件内容
	     * @param remoteFile 原文件路径
	     * @param in 追加内容
	     * @return true成功,false失败
	     */
	    public static boolean appendFileContent(String remoteFile, InputStream in){
	        boolean resultState=false;
	        FTPUtils sftpUtil = new FTPUtils();
	        try{
	            getConnect(sftpUtil,CHANNELTYPE_SFTP);//建立连接
	            Session session = sftpUtil.getSession();
	            Channel channel = sftpUtil.getChannel();
	            ChannelSftp sftp = sftpUtil.getSftp();// sftp操作类
	            OutputStream out = sftp.put(remoteFile, ChannelSftp.APPEND);
	            int bufferSize=1024;
	            byte[] buff = new byte[bufferSize]; // 设定每次传输的数据块大小
	            int read;
	            if (out != null) {
	                do {
	                    read = in.read(buff, 0, buff.length);
	                    if (read > 0) {
	                        out.write(buff, 0, read);
	                    }
	                    out.flush();
	                } while (read >= 0);
	            }
	            if(out!=null){
	                out.close();
	            }
	            closeConnect(session, channel, sftp);
	            resultState=true;
	        }catch (Exception e){
	            System.out.println("写入文件异常");
	        }
	        return resultState;
	    }

	    /**
	     * 创建文件
	     * @param fileDir 文件路径
	     * @param fileName 文件名称
	     * @return
	     */
	    public static boolean createFile(String fileDir,String fileName){
	        try{
	            execute("mkdir -p "+fileDir+"\n" +
	                    "touch "+fileDir+"/"+fileName);
	        }catch (Exception e){
	            return false;
	        }
	        return true;
	    }

	    /**
	     * 创建文件夹
	     * @param fileDir 文件路径
	     * @return true成功/false失败
	     */
	    public static boolean createFileDir(String fileDir){
	        try{
	            execute("mkdir -p "+fileDir+"");
	        }catch (Exception e){
	            return false;
	        }
	        return true;
	    }

	    /**
	     * 压缩文件夹为ZIP
	     * @param fileDir 文件路径
	     * @param fileName 文件名称
	     * @param additionalName 压缩附加名
	     * @return
	     */
	    public static boolean zipDir(String fileDir,String fileName,String additionalName){
	        try{
	            execute("cd "+fileDir+"\n" +
	                    "zip  -r "+fileDir+"/"+fileName+additionalName+".zip "+fileName);
	        }catch (Exception e){
	            return false;
	        }
	        return true;
	    }

	    /**
	     * 获取文件大小 单位(K)
	     * @param fileDir 文件路径
	     * @return 文件大小
	     */
	    public static long getFileSize(String fileDir){
	        return Long.parseLong(execute("ls -l "+fileDir+" | awk '{ print $5 }'"));
	    }
	    /**
	     * 执行liunx 命令
	     * @param command 命令内容
	     * @return 命令输出
	     */
	    public static String execute(String command){
	        FTPUtils sftpUtil=new FTPUtils();
	        StringBuffer strBuffer=new StringBuffer();
	        try {
	            getConnect(sftpUtil,CHANNELTYPE_EXEC);
	            // Create and connect session.
	            Session session = sftpUtil.getSession();

	            // Create and connect channel.
	            Channel channel = session.openChannel("exec");
	            ((ChannelExec) channel).setCommand(command);

	            channel.setInputStream(null);
	            BufferedReader input = new BufferedReader(new InputStreamReader(channel
	                    .getInputStream()));

	            channel.connect();
	            System.out.println("命令: " + command);
	            // 获取命令的输出
	            String line;
	            while ((line = input.readLine()) != null) {
	                strBuffer.append(line);
	            }
	            input.close();
	            closeConnect(session,channel,null);
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	        return strBuffer.toString();
	    }

}

 

b.main方法:

public static void main(String[] args) throws FileNotFoundException {
	        String window_dir="D:/testimg/QQ图片20200411163750.jpg";
	        String liunx_dir="/home/ytyfemall/upload/uxunimg/test/img";
	        try {
	            System.out.println(upload(liunx_dir,window_dir));
	            //System.out.println(download(liunx_dir,"test.txt","C:\\Users\\XXX\\Desktop\\test"));
	            System.out.println(delete(liunx_dir,"test.txt"));

	            InputStream inputStream = new ByteArrayInputStream("this is test".getBytes());
	            System.out.println(appendFileContent(liunx_dir+"/test.txt",inputStream));

	            String command="touch /usr/local/longlin/longpizi.sh\nmkdir -p sss";
	            System.out.println(execute(command));

	            //System.out.println(createFile("/home/ytyfemall/upload/uxunimg/test","sss.txt"));
	            System.out.println(upload(liunx_dir,window_dir));
	        } catch (Exception e) {
	            e.printStackTrace();
	        }
	    }

c.代码中使用,本人使用的框架(SSH+Spring+Hib)

在action中找到service

goodsService.updateGoodsInfoEmall(goodsInfoEmall,file,fileName,uplodfile);

service的实现类实现该方法:

// 上传图片信息
				if( file != null && fileName != null ){
					fileName = DateUtils.dateToDateString(new Date(), DateUtils.TIME_STR_FORMAT);
					String getResponse = uploadImageSFCP(file, fileName, goodsInfo.getGoodsid(),"1");
				}
				if(uploadfile != null ){
					if(uploadfile.length>0){
						for(int index=0;index<uploadfile.length;index++){
							fileName = DateUtils.dateToDateString(new Date(), DateUtils.TIME_STR_FORMAT);
							String fname = fileName+"_"+index;
							String getResponse = uploadImageSFCP(uploadfile[index], fname, goodsInfo.getGoodsid(),"2");
						}
						
					}
				}

具体上传实现:

public String uploadImageSFCP(File file, String fileName, String goodsId, String imgtype) throws Exception {
			log.debug("[file]--" + file);
			log.debug("[file name]--" + fileName);
			String serverRootdir = ServletActionContext.getServletContext().getRealPath(Constant.IMAGE_SAVE_FOLDER).replace(ConfigManager.getString("uxun.plat.name", "uxunplat"), ConfigManager.getString("uxun.cust.name", "jfycust"));
			String serverRootSubdir ="/" + goodsId;
			FileUtil.createFolder(serverRootdir + serverRootSubdir);	
			//	创建文件夹
			String beShowedPath = serverRootSubdir+serverRootSubdir+"_"+fileName+".jpg";
			log.info("=============>存储有地址:" + serverRootdir + beShowedPath);
			 String yyzxPath = ConfigManager.getString("YYZX_IMAGE_URL", "");
			String windowPathString = file.getAbsolutePath();
			String linuxPathString = yyzxPath+goodsId;
			String fileNameString = goodsId+"_"+fileName+".jpg";
			FTPUtils.upload(linuxPathString, windowPathString, fileNameString);
			log.info("===============>linuxPathString:"+linuxPathString);
			log.info("===============>windowPathString:"+windowPathString);
			log.info("===============>fileNameString:"+fileNameString);
}

服务器地址,本机地址,文件名称都需要自己去写,

PS:有个问题就是file上传的时候,会先找到tomcat容器下的.temp临时文件,所以上传后需要自行修改后缀名称,当然你要两台服务器可以连通,user,password,port,url都要有具体

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值