采用JSCH API(本例引用了jsch-0.1.52.jar)
官网参考 http://www.jcraft.com/jsch/
1,建立Session,对应一个用户账户,并在无传输线程时自动关闭session
public class SFTPProcessor2 { private static final Logger LOGGER = Logger.getLogger(SFTPProcessor2.class); private static Session session = null; public Session getConnect(Map<String, String> serverMap) { String ftpHost = serverMap.get(SFTPConstants.SFTP_SERVER_HOST); String port = serverMap.get(SFTPConstants.SFTP_SERVER_PORT); String ftpUserName = serverMap.get(SFTPConstants.SFTP_SERVER_USERNAME); String ftpPassword = serverMap.get(SFTPConstants.SFTP_SERVER_PASSWORD); // 默认的端口22 此处我是定义到常量类中; int ftpPort = SFTPConstants.SFTP_DEFAULT_PORT; // 判断端口号是否为空,如果不为空,则赋值 if (port != null && !port.equals("")) { ftpPort = Integer.valueOf(port); } JSch jsch = new JSch(); // 创建JSch对象 // 按照用户名,主机ip,端口获取一个Session对象 try { session = jsch.getSession(ftpUserName, ftpHost, ftpPort); LOGGER.debug("Session created."); if (ftpPassword != null) { session.setPassword(ftpPassword); // 设置密码 } // 具体config中需要配置那些内容,请参照sshd服务器的配置文件/etc/ssh/sshd_config的配置 Properties config = new Properties(); // 设置不用检查hostKey // 如果设置成“yes”,ssh就会自动把计算机的密匙加入“$HOME/.ssh/known_hosts”文件, // 并且一旦计算机的密匙发生了变化,就拒绝连接。 config.put("StrictHostKeyChecking", "no"); // UseDNS指定,sshd的是否应该看远程主机名,检查解析主机名的远程IP地址映射到相同的IP地址。 // 默认值是 “yes” 此处是由于我们SFTP服务器的DNS解析有问题,则把UseDNS设置为“no” config.put("UseDNS", "no"); session.setConfig(config); // 为Session对象设置properties session.setTimeout(SFTPConstants.SFTP_DEFAULT_TIMEOUT); // 设置timeout时候 session.connect(); // 经由过程Session建树链接 LOGGER.debug("Session connected."); } catch (JSchException e) { // TODO Auto-generated catch block e.printStackTrace(); } return session; } /* public boolean upfile(InputStream is, OutputStream os) throws IOException{ boolean res = false; byte[] b = new byte[1024*1024*100]; int read; if(os!=null){ do { read = is.read(b, 0, b.length); if (read > 0) { os.write(b, 0, read); } os.flush(); } while (read >= 0); } return res; }*/ /* public void uploadFile(String localFile, String newName, String remoteFoldPath) // throws AppBizException { InputStream input = null; OutputStream os = null; try { File lf = new File(localFile); input = new FileInputStream(lf); // 改变当前路径到指定路径 channel.cd(remoteFoldPath); long t1 = System.currentTimeMillis(); //channel.put(input, newName); os = channel.put(newName //, new ProgressMonitor(lf.length()) // 上传时不执行init()方法 ,new ProgressMonitorByBytes(lf.length()) ,ChannelSftp.OVERWRITE) ; upfile(input,os); channel.put(localFile , newName , new ProgressMonitorByBytes() , ChannelSftp.OVERWRITE); System.out.println("Time elapsed: " + (System.currentTimeMillis() - t1) + "(ms)"); } catch (Exception e) { LOGGER.error("Upload file error", e); } finally { if (input != null) { try { input.close(); } catch (IOException e) { } } if (os != null) { try { os.close(); } catch (IOException e) { } } } }*/ public static void main(String[] args) throws Exception { SFTPProcessor2 ftpUtil = new SFTPProcessor2(); Map<String, String> ftpServerMap = new HashMap<String, String>(); ftpServerMap.put((String) SFTPConstants.SFTP_SERVER_HOST, "localhost"); ftpServerMap.put((String) SFTPConstants.SFTP_SERVER_USERNAME, "name"); ftpServerMap.put((String) SFTPConstants.SFTP_SERVER_PASSWORD, "password"); ftpServerMap.put((String) SFTPConstants.SFTP_SERVER_PORT, "22"); ftpUtil.getConnect(ftpServerMap); //ftpUtil.uploadFile("e:/eclipse-jee.zip", "eclipse-jee.zip", System.getProperty("file.separator")); String rf1 = "eclipse-jee.zip"; String rp1 = System.getProperty("file.separator")+"d"; //String rp1 = ""; String rf2 = "zzzz.zip"; String rp2 = System.getProperty("file.separator")+"d"; //String rp2 = ""; String lf1 = "e:/yyyy.zip"; String lf2 = "e:/zzzz.zip" ; DownLoadThread d1 = new DownLoadThread(session,rf1,rp1,lf1, ftpServerMap.get((String) SFTPConstants.SFTP_SERVER_HOST), ftpServerMap.get((String) SFTPConstants.SFTP_SERVER_USERNAME), "TRANS100"); DownLoadThread d2 = new DownLoadThread(session,rf2,rp2,lf2, ftpServerMap.get((String) SFTPConstants.SFTP_SERVER_HOST), ftpServerMap.get((String) SFTPConstants.SFTP_SERVER_USERNAME), "TRANS99"); final Thread t1 = new Thread(d1); final Thread t2 = new Thread(d2); t1.start(); t2.start(); final List<Thread> lst = new ArrayList<Thread>(); lst.add(t1); lst.add(t2); //ftpUtil.downloadFile("eclipse-jee.zip", System.getProperty("file.separator")+"d", "e:/zzzz.zip"); //ftpUtil.downloadFile("snagit.zip", System.getProperty("file.separator")+"d", "e:/test20150608.zip"); Thread t3 = new Thread(new Runnable(){ @Override public void run() { while(true){ boolean nonlive = true; for (int i = 0; i < lst.size(); i++) { if(lst.get(i).isAlive()){ nonlive = false; break; } } if( nonlive ){ System.out.println("No Active transmission, exit!"); session.disconnect(); break; } } } }); //t3.setDaemon(true); t3.start(); } }
2,建立通道,多线程下载
public class DownLoadThread implements Runnable { private static final Logger LOGGER = Logger.getLogger(SFTPProcessor2.class); private ChannelSftp channel = null; private Session session = null; private ProgressMonitorByBytes monitor = null; private String remotef = null; private String remotep = null; private String lf = null; private String ftpuser = null; private String ftphost = null; private String transid = null; public DownLoadThread(Session ss , String rf ,String rp, String lf ,String host, String user,String tid) { this.session = ss; //this.monitor = p; this.remotef = rf; this.remotep = rp; this.lf = lf; this.ftphost = host; this.ftpuser = user; this.transid = tid; } @Override public void run() { try { channel = getOpenCh(session,ftphost,ftpuser); monitor = new ProgressMonitorByBytes(transid,remotef,this.getRemoteFilesize1(channel,remotef,remotep)); downloadFile(this.remotef,this.remotep,this.lf); closeChannel(); //Thread.currentThread().interrupt(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } public ChannelSftp getOpenCh(Session ss ,String ftphost,String ftpusername){ try { LOGGER.debug("Opening SFTP Channel."); channel = (ChannelSftp) ss.openChannel("sftp"); // 打开SFTP通道 channel.connect(); // 建树SFTP通道的连接 LOGGER.debug("Connected successfully to ftpHost = " + ftphost + ",as ftpUserName = " + ftpusername + ", returning: " + channel); } catch (JSchException e) { // TODO Auto-generated catch block e.printStackTrace(); } return channel; } public void closeChannel() { try { if (channel != null) { channel.disconnect(); } } catch (Exception e) { LOGGER.error("close sftp error", e); // throw new AppBizException(AppExcCodes.CLOSE_FTP_ERROR, // "close ftp error."); } } public void downloadFile(String remoteFile, String remotePath,String localFile) { OutputStream output = null; File file = null; try { file = new File(localFile); if (!checkFileExist(localFile)) { file.createNewFile(); output = new FileOutputStream(file); channel.cd(remotePath); //channel.get(remoteFile, output); channel.get(remoteFile, localFile //, new ProgressMonitor(getRemoteFilesize1(channel,remoteFile,remotePath)) ,monitor , ChannelSftp.OVERWRITE); }else{ //output = new FileOutputStream(file); channel.cd(remotePath); channel.get(remoteFile, localFile //, new ProgressMonitor(getRemoteFilesize1(channel,remoteFile,remotePath)) ,monitor , ChannelSftp.RESUME); } } catch (Exception e) { LOGGER.error("Download file error", e); } finally { if (output != null) { try { output.close(); } catch (IOException e) { } } if (file != null) { //file.delete(); } } } private boolean checkFileExist(String localPath) { File file = new File(localPath); return file.exists(); } public long getRemoteFilesize1(ChannelSftp cf , String remoteFile,String remotepath ) { Object o = null; long s = 0; try { Vector v = cf.ls(cf.pwd() + "/" + remotepath + "/" + remoteFile); if(v!=null && v.size() == 1){ o = v.firstElement(); } //System.out.println(); LsEntry cl = (LsEntry)o; s = cl.getAttrs().getSize(); System.out.println(s + "(bytes)"); } catch (SftpException e) { // TODO Auto-generated catch block e.printStackTrace(); } return s; } }
3,下载进度监控,控制取消,限制速度等
public class ProgressMonitorByBytes implements SftpProgressMonitor { private long transfered; private long filesize; private String remotef; private Formatter f = null; private long stime; private long etime; private String transferID ; public ProgressMonitorByBytes(String transid,String remotefile, long totalsize ) { this.filesize = totalsize; this.remotef = remotefile; this.transferID = transid ; } public void sendmsg(){ DecimalFormat df = new DecimalFormat( "#.##"); String per = df.format(100*(1.0f*transfered/filesize)); System.out.println("Currently transferred total size: " + transfered + " bytes, percent: " + per + "% [" + remotef + "]" ); f.format("%1$10s\n","Currently transferred total size: " + transfered + " bytes, percent: " + per + "% [" + remotef + "] " ); } @Override public boolean count(long count) { long now = System.currentTimeMillis(); long timeelapse = (now - stime); boolean cancelCondition = (timeelapse > 10*1000) && "TRANS1000".equals(transferID); if(transfered != filesize ) { sendmsg(); transfered = transfered + count; if(cancelCondition){ //作为取消下载使用,可以取消(暂停下载) f.format("%1$10s\n","Cancel transfer: [" + remotef + "]"); System.out.printf("%1$10s\n","Cancel transfer: [" + remotef + "]"); return false; } boolean sleepCondition = (1000 * (1.0d/1024) * transfered / timeelapse ) > 4096 ; if(sleepCondition){ try { Thread.currentThread().sleep(1000); //作为限速使用,貌似可以限制下载速度 } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return true; } return false; } @Override public void end() { etime = System.currentTimeMillis(); sendmsg(); System.out.println("Transferring done. [" + remotef + "]"); f.format("%1$10s\n", "Transferring done. [" + remotef + "]"); f.format("%1$10s\n", "Time Elapsed:"+ getTimePassed(etime - stime) +" [" + remotef + "]"); f.close(); } public String getTimePassed(long times){ String res = ""; long hours = 0; long minutes = 0 ; long seconds = 0 ; long millseconds = 0; hours = times / (1000*60*60); minutes = (times - hours * (1000*60*60)) / (1000*60); seconds = (times - hours * (1000*60*60) - minutes*1000*60) / 1000; millseconds = times - hours * (1000*60*60) - minutes*1000*60 - seconds*1000; res = Long.toString(hours, 10)+"小时" + Long.toString(minutes, 10)+"分钟"+ Long.toString(seconds, 10)+"秒"+ Long.toString(millseconds, 10)+"毫秒"; return res; } /** * @param arg0 1:下载,0:上传 * @param arg1 原始文件PATH * @param arg2 目标文件PATH * @param arg3 文件大小 * * */ @Override public void init(int arg0, String arg1, String arg2, long arg3) { stime = System.currentTimeMillis(); try { f = new Formatter(new FileOutputStream("E:/xdownlog.log", true)); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } f.format("%1$10s\n", "Transferring begin. [" + remotef + "]"); //filesize = arg3; System.out.println("Transferring begin. [" + remotef + "]"); System.out.println("======================"); System.out.println(arg0);System.out.println(arg1);System.out.println(arg2);System.out.println(arg3); System.out.println("======================"); } }
4,配置用的常量
public class SFTPConstants { public static final int SFTP_DEFAULT_TIMEOUT = 0; public static final Object SFTP_SERVER_HOST = "SFTP_SERVER_HOST"; public static final Object SFTP_SERVER_PORT = "SFTP_SERVER_PORT"; public static final Object SFTP_SERVER_USERNAME = "SFTP_SERVER_USERNAME"; public static final Object SFTP_SERVER_PASSWORD = "SFTP_SERVER_PASSWORD"; public static final int SFTP_DEFAULT_PORT = 22; }
相关推荐
1. 把每个下载文件切成若干个块(Block),然后得到一个位图,用来标记每个块的下载情况,并保存到文件里,用于实现断点续传。 2. HTTP Header里增加Range,如果服务器返回Cotent-Range 说明服务器支持文件定位,可以...
2、支持多任务多线程同时下载; 3、每个任务的线程数由用户在新建任务时自定义,缺省为5个线程; 4、任务下载过程中可以点击“线程+”或“线程-”即时增减线程; 5、选择任务,可以在任务信息栏中查看任务下载的信息...
Linux下的SFTP C语言客户端,包括SFTP下载、上传、list目录和创建目录,依赖libssh2库,该库可自行下载编译安装。 全部源代码,可编译和测试。
一个很不错FTP软件,图形化列表,断点续传。
自己用python写的断点续传脚本
sftp 客户端服务程序 基于 sftp通讯协议~~
此代码基于python实现了服务器/客户端的断点续传,可以作为网络编程中的参考。
适用多线程的SFTP类,支持代理服务器,是spring服务类,无需修改可直接与spring结合使用。 代码经过大量的并发使用验证,稳定可靠。 依赖的jar包如下: <groupId>com.jcraft</groupId> <artifactId>...
vc实现的ftp客户端断点续传: __fastcall TMultiFtp::TMultiFtp(TComponent* Owner) : TComponent(Owner) { lock = false; isUseFile = false; runningThreadCnt = 0; stop = false; this->Owner = Owner; }
SFTP 客户端 SFTP 客户端工具 适用于windowSFTP 客户端工具 适用于window
Windows环境下使用SSH的开源图形化SFTP客户端。同时支持SCP协议。它的主要功能就是在本地与远程计算机间安全的复制传输文件。 WinSCP传输模式可以选择FTP、SFTP、SCP、WebDAV 4种模式,默认为SFTP模式,我们一般用前...
该资源为python实现可配置的sftp传输,get和put 配置文件为.ini文件;put和get区分一下源和目的路径,基本配置项即说明如下: [ftp]:ftp基本信息 [common] 公共的配置 如日志信息,传输模式,是否递归,是否删除等 ...
Qt下的ftp/sftp下载客户端,支持断点续传,支持检测下载文件是否存在,支持进度条
WinSCP 是一个 Windows 环境下使用的 SSH 的开源图形化 SFTP 客户端。同时支持 SCP 协议。它的主要功能是在本地与远程计算机间安全地复制文件,并且可以直接编辑文件。 WinSCP 中文绿色版WinSCP 中文绿色版 WinSCP...
WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端。同时支持SCP协议。
WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端。同时支持SCP协议。它的主要功能就是在本地与远程计算机间安全的复制文件。.winscp也可以链接其他系统,比如linux系统
用c语言实现文件的上传和下载...使用ftp协议,实现断点续传功能。文件包中包含完整的源代码。能编译通过。 用c语言实现文件的上传和下载功能;使用ftp协议,实现断点续传功能。文件包中包含完整的源代码。能编译通过。
在安装目录拷贝该目录下的所有文件到C#可执行程序目录)打开winscp,然后自动连上SFTP服务器,这样就可以直接使用winscp来进行操作了,比如文件上传、下载和删除等,省去自己去写一个sftp客户端,非常方便。...
WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端。同时支持SCP协议。它的主要功能就是在本地与远程计算机间安全的复制文件。
注意,本文所说的断点续传特指 HTTP 协议中的断点续传。本文主要聊聊思路和关键代码,更多细节请参考本文附带的 demo。 工作原理 HTTP 协议中定义了一些请求/响应头,通过组合使用这些头信息。我们可以在一次 HTTP ...