采用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; }
相关推荐
4. **断点续传**:如果下载过程中因网络问题中断,具备断点续传功能的FTP工具可以记录已下载的部分,在恢复连接后继续从上次断点处下载,避免了重头开始。 5. **批量下载**:用户可以一次性添加多个文件或整个目录...
3. **高性能传输**:LeapFTP支持断点续传功能,即使在传输过程中遇到网络问题,也能从上次中断的地方继续,避免了重复下载或上传的麻烦。此外,它的传输速度稳定,能充分利用网络带宽,确保大文件快速、安全地传输。...
Aria2c是一款轻量级的命令行下载工具,支持HTTP(S)、FTP、SFTP、BitTorrent等多种协议,并且具有断点续传和限速等功能。 首先,我们要理解C++是面向对象的编程语言,它的强大性能和灵活性使得它成为开发系统级和高...
Aria2是一款强大的下载管理器,支持HTTP(S)、FTP、SFTP、BitTorrent等多种协议,并且能够实现断点续传和多线程下载,极大地提高了下载效率。 首先,让我们深入了解一下Aria2的核心功能。Aria2是一个命令行工具,...
2. 断点续传:记录已下载部分,中断后可以从上次断点继续下载。 3. 重试机制:在网络不稳定时自动重试,保证文件完整下载。 4. 限速控制:避免对服务器造成过大压力,可以设定下载速度上限。 六、安全性考虑 1. ...
2. **分块下载与断点续传**:`aria2`可以将大文件分割成多个部分同时下载,并且在下载过程中支持断点续传,即使下载中断,也能从上次中断的地方继续。 3. **限速与优先级设置**:用户可以根据网络状况设定下载速度...
此外,xdown可能还具备断点续传、计划下载、限速设置等实用功能,以满足不同用户的需求。 接下来,我们转向aria2,这是一款开源的、轻量级的下载管理器。aria2支持HTTP(S)、FTP、SFTP、BitTorrent等多种协议,能...
它能够充分利用你的网络带宽,几乎达到理论上的最大下载速度,这是因为aria2采用了多线程、多源下载的技术,将文件从多个源同时下载,从而显著提高了下载效率。无论是HTTP、HTTPS,还是磁力链接(Magnet)或者BT种子...
3. **断点续传**:如果文件传输中断,可以从上次断点处继续,避免重新下载整个文件。 4. **批量传输**:支持一次性传输多个文件,提高工作效率。 5. **多线程传输**:利用IPv6的多路复用能力,同时处理多个文件传输...
3. **断点续传**:如果下载中断,Aria2可以记住已下载的部分并在稍后恢复下载。 4. **限速和优先级设置**:用户可以根据需要设置下载速度限制,还可以为不同任务设置优先级。 5. **JSON-RPC和Web界面**:Aria2可以...
此外,aria2还具有断点续传和多线程下载的特点,可以有效利用网络资源,提高下载效率。 **主要特点** 1. **多源下载**:aria2可以从多个源同时下载同一个文件,通过分散负载,提高下载速度。 2. **分块下载**:将...
"aria2 解除限速"这一标签暗示了Aria2的一个关键特性,即它可以通过多源、多线程的下载方式,可能帮助用户绕过某些下载服务的限速策略,提高下载速度。这在处理大型文件或者面对网络限制时尤其有用。 **Aria2的详细...
FTP(File Transfer Protocol)是一种基于TCP/IP协议的网络协议,用于在网络上进行文件传输。本项目实现了FTP的客户端...在实际开发中,还可以根据需求添加更多特性,比如支持断点续传、限速控制、文件上传进度显示等。
1. **Aria2特点**: Aria2是一个高性能的下载工具,支持断点续传、多线程、多源下载,能有效地提高下载速度和稳定性。 2. **协议支持**: Aria2可以处理多种下载协议,包括HTTP(S)、FTP、SFTP,以及P2P协议如...
3. **断点续传**:支持暂停和恢复下载,即使在下载过程中出现网络中断,也可以从上次中断的地方继续。 4. **限速控制**:允许用户设定下载速度上限,避免影响其他网络应用。 5. **磁力链接与BT下载**:除了常规URL,...
它支持HTTP(S)、FTP、SFTP、BT(BitTorrent)和磁力链接等多种下载方式,而且具备断点续传、限速控制、多线程下载等功能。Aria2以其高效、稳定和资源占用低的特点,受到了许多用户的喜爱。然而,由于其命令行操作和...
1. **多线程传输**:允许同时传输多个文件,提高上传或下载速度。 2. **断点续传**:如果文件传输过程中因网络问题中断,可以从上次断开的地方继续,避免重新传输整个文件。 3. **书签功能**:保存常用的FTP服务器...
3. **断点续传**:如果下载过程中因网络问题中断,Aria2能够记住已下载的部分并在恢复连接后继续下载,避免了重新开始的麻烦。 4. **限速与调度**:用户可以设置下载和上传的速度限制,以适应不同的网络环境和需求...
4. **断点续传**:如果下载中断,Aria2可以继续从上次停止的地方开始下载。 5. **JSON-RPC和Web界面**:Aria2可以通过JSON-RPC接口进行远程控制,还可以安装Web界面进行图形化管理。 对于开发者而言,Aria2的SDK...