package com.sssppp.Communication;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.PrintWriter;import java.io.RandomAccessFile;import org.apache.commons.net.PrintCommandListener;import org.apache.commons.net.ftp.FTP;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.net.ftp.FTPClientConfig;import org.apache.commons.net.ftp.FTPFile;import org.apache.commons.net.ftp.FTPReply;import org.apache.commons.net.io.CopyStreamEvent;import org.apache.commons.net.io.CopyStreamListener;/** * FTP进行文件上传和下载; * 支持断点续传; */public final class FTPUtil { private final FTPClient ftp = new FTPClient(); /** * * @param hostname * 如:IP * @param port * @param username * @param password * @return * @throws IOException */ public boolean connect(String hostname, int port, String username, String password) throws IOException { boolean debug = false; if (debug) { // 设置将过程当中使用到的命令输出到控制台 this.ftp.addProtocolCommandListener(new PrintCommandListener( new PrintWriter(System.out), true)); } //设置系统类型 final FTPClientConfig config = new FTPClientConfig( FTPClientConfig.SYST_UNIX); this.ftp.configure(config); try { this.ftp.connect(hostname, port); if (!FTPReply.isPositiveCompletion(this.ftp.getReplyCode())) { this.ftp.disconnect(); System.err.println("FTP server refused connection."); return false; } } catch (IOException e) { if (this.ftp.isConnected()) { try { this.ftp.disconnect(); } catch (IOException f) { } } System.err.println("Could not connect to server."); e.printStackTrace(); return false; } if (!this.ftp.login(username, password)) { this.ftp.logout(); System.err.println("Could not login to server."); return false; } return true; } public void disconnect() throws IOException { if (this.ftp.isConnected()) { try { this.ftp.logout(); this.ftp.disconnect(); } catch (IOException f) { } } } /** * * @param absSrcFileName * @param destDir * @param destFileName * @throws IOException */ public void upLoadByFtp(String absSrcFileName, String destDir, String destFileName) throws IOException { // 建立并转到工做目录 String absDstDir = this.ftp.printWorkingDirectory() + "/" + destDir; absDstDir = absDstDir.replaceAll("//", "/"); createDirectory(absDstDir, this.ftp); // 设置各类属性 this.ftp.setFileType(FTP.BINARY_FILE_TYPE); // Use passive mode as default because most of us are behind firewalls these days. this.ftp.enterLocalPassiveMode(); this.ftp.setControlEncoding("utf-8"); this.ftp.setBufferSize(1024); // 进度监听 File srcFile = new File(absSrcFileName); this.ftp.setCopyStreamListener(new MyCopyStreamListener(srcFile.length())); FTPFile[] files = this.ftp.listFiles(destFileName); if (files.length == 1) {// 断点续传 long dstFileSize = files[0].getSize(); if (srcFile.length() <= dstFileSize) {// 文件已存在 return; } boolean b = uploadFile(destFileName, srcFile, this.ftp, dstFileSize); if (!b) {// 若是断点续传没有成功,则删除服务器上文件,从新上传 if (this.ftp.deleteFile(destFileName)) { uploadFile(destFileName, srcFile, this.ftp, 0); }else { System.err.println("Delete file fail."); } } } else { uploadFile(destFileName, srcFile, this.ftp, 0); } } /** * * @param remoteFileName * @param localFileName * @throws IOException */ public void downLoadByFtp(String remoteFileName, String localFileName) throws IOException { InputStream input = null; FileOutputStream fos = null; // 设置各类属性 this.ftp.setBufferSize(1024); this.ftp.setDataTimeout(1000 * 10); this.ftp.setFileType(FTPClient.BINARY_FILE_TYPE); this.ftp.enterLocalPassiveMode(); // 判断远程文件是否存在 FTPFile[] files = this.ftp.listFiles(remoteFileName); if (files.length != 1) { System.err.println("Remote file not exist."); return; } //进度监听 long remoteSize = files[0].getSize(); this.ftp.setCopyStreamListener(new MyCopyStreamListener(remoteSize)); File file = new File(localFileName); if (file.exists()) { long localSize = file.length(); if (localSize >= remoteSize) { return; } System.out.println("@@@Break point download.@@@"); fos = new FileOutputStream(file, true);// append模式 this.ftp.setRestartOffset(localSize); } else { fos = new FileOutputStream(file); // override模式 } input = this.ftp.retrieveFileStream(remoteFileName); byte[] b = new byte[8192]; int n = 0; while (-1 != (n = input.read(b))) { if (Thread.currentThread().isInterrupted()) { break; } fos.write(b, 0, n); } if (input != null) { input.close(); } if (fos != null) { fos.flush(); fos.close(); } if (!this.ftp.completePendingCommand()) { System.err.println("Download file fail."); this.ftp.logout(); this.ftp.disconnect(); } } /** * * @param destFileName * @param srcFile * @param ftpClient * @param dstFileSize 文件写入的起始位置; >0:表示断点续传,<=0:表示上传新文件 * @return * @throws IOException */ private boolean uploadFile(String destFileName, File srcFile, FTPClient ftpClient, long dstFileSize) throws IOException { RandomAccessFile input = null; OutputStream fout = null; input = new RandomAccessFile(srcFile, "r"); // 只读模式 if (dstFileSize > 0) {// 断点续传 fout = ftpClient.appendFileStream(destFileName); input.seek(dstFileSize); ftpClient.setRestartOffset(dstFileSize); } else { fout = ftpClient.storeFileStream(destFileName); } byte[] b = new byte[8192]; // 缓存大小 int n = 0; while (-1 != (n = input.read(b))) { if (Thread.currentThread().isInterrupted()) { break; } fout.write(b, 0, n); } if (input != null) { input.close(); } if (fout != null) { fout.flush(); fout.close(); } if (!ftpClient.completePendingCommand()) { System.err.println("Upload file fail."); ftpClient.logout(); ftpClient.disconnect(); return false; } return true; } /** * 在FTP服务器上建立并转到工做目录 * * @param relativePath * 相对工做路径,不包含文件名:如 dd/11/22/33 * @param ftpClient * 录建立是否成功 * @return * @throws IOException */ private boolean createDirectory(String relativePath, FTPClient ftpClient) throws IOException { if (!relativePath.startsWith("/")) { relativePath = "/" + relativePath; } String dir = (ftpClient.printWorkingDirectory().equals("/") ? "" : ftpClient.printWorkingDirectory()) + relativePath; if (!ftpClient.changeWorkingDirectory(dir)) { //目录不存在,则建立各级目录 for (String subDir : relativePath.split("/")) { if (!subDir.equals("")) { String newDir = ftpClient.printWorkingDirectory() + "/" + subDir; ftpClient.mkd(newDir); if (!ftpClient.changeWorkingDirectory(newDir)) { return false; } } } } return true; } /** * 进度监听器 */ private class MyCopyStreamListener implements CopyStreamListener { private long totalSize = 0; private long percent = -1; // 进度 /** * 文件的总大小 * @param totalSize */ public MyCopyStreamListener(long totalSize) { super(); this.totalSize = totalSize; } @Override public void bytesTransferred(CopyStreamEvent event) { bytesTransferred(event.getTotalBytesTransferred(), event.getBytesTransferred(), event.getStreamSize()); } //totalBytesTransferred:当前总共已传输字节数; //bytesTransferred:最近一次传输字节数 @Override public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) { if (percent >= totalBytesTransferred * 100 / totalSize) { return; } percent = totalBytesTransferred * 100 / totalSize; System.out.println("Completed " + totalBytesTransferred + "(" + percent + "%) out of " + totalSize + "."); } } public static void main(String[] args) throws IOException { String hostname = "10.180.137.241"; String username = "xxx"; String password = "xxx"; int port = 21; FTPUtil ftp = new FTPUtil(); //上传文件 String absSrcFileName = "C:\\tmp\\m2eclipse1.zip"; String destDir = "ww/11/22/33"; String destFileName = "m2eclipse1.zip"; ftp.connect(hostname, port, username, password); ftp.upLoadByFtp(absSrcFileName, destDir, destFileName); ftp.disconnect(); // 下载文件 String localFileName = "C:\\tmp\\m2eclipse-download3333.zip"; String remoteFileName = "/ww/11/22/33/m2eclipse.zip"; ftp.connect(hostname, port, username, password); ftp.downLoadByFtp(remoteFileName, localFileName); ftp.disconnect(); }}