package cn.ksource.core.util; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Properties; import cn.ksource.web.Constants; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; public class FtpClient { public FTPClient ftpClient = new FTPClient(); /** * java编程中用于连接到FTP服务器 * * @param hostname * 主机名 * @param port * 端口 * @param username * 用户名 * @param password * 密码 * @return 是否连接成功 * @throws IOException */ public boolean connect() throws IOException { Properties props = new Properties(); InputStream in = FtpClient.class.getResourceAsStream("/"+ Constants.APP_CONF_FILE); props.load(in); in.close(); String url = props.getProperty("ftp.url"); String port = props.getProperty("ftp.port"); String username = props.getProperty("ftp.username"); String password = props.getProperty("ftp.pwd"); ftpClient.connect(url, Integer.valueOf(port)); ftpClient.setControlEncoding("GBK"); if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { if (ftpClient.login(username, password)) { System.out.println("ftp登陆成功"); return true; } } disconnect(); return false; } /** * 从FTP服务器上下载文件 * * @param remote * 远程文件路径 * @param local * 本地文件路径 * @return 是否成功 * @throws IOException */ public DownloadStatus download(String remote, String local) throws IOException { ftpClient.enterLocalPassiveMode(); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); DownloadStatus result; FTPFile[] files = ftpClient.listFiles(remote); if (files.length != 1) { System.out.println("远程文件不唯一"); return DownloadStatus.Remote_File_Noexist; } long lRemoteSize = files[0].getSize(); File f = new File(local); if (f.exists()) { long localSize = f.length(); if (localSize >= lRemoteSize) { System.out.println("本地文件大小大于远程文件大小,下载中止"); return DownloadStatus.Local_Bigger_Remote; } FileOutputStream out = new FileOutputStream(f, true); ftpClient.setRestartOffset(localSize); InputStream in = ftpClient.retrieveFileStream(remote); byte[] bytes = new byte[1024]; long step = lRemoteSize / 100; long process = localSize / step; int c; while ((c = in.read(bytes)) != -1) { out.write(bytes, 0, c); localSize += c; long nowProcess = localSize / step; if (nowProcess > process) { process = nowProcess; if (process % 10 == 0) System.out.println(process); } } in.close(); out.close(); boolean isDo = ftpClient.completePendingCommand(); if (isDo) { result = DownloadStatus.Download_From_Break_Success; } else { result = DownloadStatus.Download_From_Break_Failed; } } else { OutputStream out = new FileOutputStream(f); InputStream in = ftpClient.retrieveFileStream(remote); byte[] bytes = new byte[1024]; long step = lRemoteSize / 100; long process = 0; long localSize = 0L; int c; while ((c = in.read(bytes)) != -1) { out.write(bytes, 0, c); localSize += c; long nowProcess = localSize / step; if (nowProcess > process) { process = nowProcess; if (process % 10 == 0) System.out.println(process); } } in.close(); out.close(); boolean upNewStatus = ftpClient.completePendingCommand(); if (upNewStatus) { result = DownloadStatus.Download_New_Success; } else { result = DownloadStatus.Download_New_Failed; } } return result; } /** * 从FTP服务器上下载文件 * * @param remote * 远程文件路径 * @param local * 本地文件路径 * @return 是否成功 * @throws IOException */ public InputStream download(String remote) throws IOException { ftpClient.enterLocalPassiveMode(); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); //ftpClient.setRestartOffset(1000); String remoteFileNameFormat = new String(remote.getBytes("GBK"),"iso-8859-1"); InputStream in = ftpClient.retrieveFileStream(remoteFileNameFormat); //ftpClient.completePendingCommand(); return in; } public boolean exist(String remote) { try { FTPFile[] files = ftpClient.listFiles(remote); if (files.length == 1) { return true; } return false; } catch (Exception e) { e.printStackTrace(); } return false; } /** * ftp文件删除 * * @param remote * @return * @version V1.0.0 * @author * @date Oct 29, 2013 1:13:59 PM */ public boolean deleteFile(String remote) { try { if (exist(remote)) { return this.ftpClient.deleteFile(remote); } } catch (Exception e) { e.printStackTrace(); } return false; } /** * 上传文件到FTP服务器,支持断点续传 * * @param local * 本地文件名称,绝对路径 * @param remote * 远程文件路径,使用/home/directory1/subdirectory/file.ext * 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构 * @return 上传结果 * @throws IOException */ public UploadStatus upload(String local, String remote) throws IOException { // 设置PassiveMode传输 ftpClient.enterLocalPassiveMode(); // 设置以二进制流的方式传输 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); UploadStatus result; // 对远程目录的处理 String remoteFileName = remote; if (remote.contains("/")) { remoteFileName = remote.substring(remote.lastIndexOf("/") + 1); String directory = remote.substring(0, remote.lastIndexOf("/") + 1); if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory)) { // 如果远程目录不存在,则递归创建远程服务器目录 int start = 0; int end = 0; if (directory.startsWith("/")) { start = 1; } else { start = 0; } end = directory.indexOf("/", start); while (true) { String subDirectory = remote.substring(start, end); if (!ftpClient.changeWorkingDirectory(subDirectory)) { if (ftpClient.makeDirectory(subDirectory)) { ftpClient.changeWorkingDirectory(subDirectory); } else { System.out.println("创建目录失败"); return UploadStatus.Create_Directory_Fail; } } start = end + 1; end = directory.indexOf("/", start); // 检查所有目录是否创建完毕 if (end <= start) { break; } } } } String remoteFileNameFormat = new String(remoteFileName.getBytes("GBK"),"iso-8859-1"); // 检查远程是否存在文件 FTPFile[] files = ftpClient.listFiles(remoteFileName); if (files.length == 1) { long remoteSize = files[0].getSize(); File f = new File(local); long localSize = f.length(); if (remoteSize == localSize) { return UploadStatus.File_Exits; } else if (remoteSize > localSize) { return UploadStatus.Remote_Bigger_Local; } // 尝试移动文件内读取指针,实现断点续传 InputStream is = new FileInputStream(f); if (is.skip(remoteSize) == remoteSize) { ftpClient.setRestartOffset(remoteSize); if (ftpClient.storeFile(remoteFileNameFormat, is)) { is.close(); return UploadStatus.Upload_From_Break_Success; } } // 如果断点续传没有成功,则删除服务器上文件,重新上传 if (!ftpClient.deleteFile(remoteFileName)) { return UploadStatus.Delete_Remote_Faild; } is = new FileInputStream(f); if (ftpClient.storeFile(remoteFileNameFormat, is)) { result = UploadStatus.Upload_New_File_Success; } else { result = UploadStatus.Upload_New_File_Failed; } is.close(); } else { InputStream is = new FileInputStream(local); if (ftpClient.storeFile(remoteFileNameFormat, is)) { result = UploadStatus.Upload_New_File_Success; } else { result = UploadStatus.Upload_New_File_Failed; } is.close(); } return result; } /** * 上传文件到FTP服务器,支持断点续传 * * @param local * 本地文件名称,绝对路径 * @param remote * 远程文件路径,使用/home/directory1/subdirectory/file.ext * 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构 * @return 上传结果 * @throws IOException */ public UploadStatus upload(InputStream is, String remote) throws IOException { // 设置PassiveMode传输 ftpClient.enterLocalPassiveMode(); // 设置以二进制流的方式传输 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); UploadStatus result; // 对远程目录的处理 String remoteFileName = remote; if (remote.contains("/")) { remoteFileName = remote.substring(remote.lastIndexOf("/") + 1); String directory = remote.substring(0, remote.lastIndexOf("/") + 1); if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory)) { // 如果远程目录不存在,则递归创建远程服务器目录 int start = 0; int end = 0; if (directory.startsWith("/")) { start = 1; } else { start = 0; } end = directory.indexOf("/", start); while (true) { String subDirectory = remote.substring(start, end); if (!ftpClient.changeWorkingDirectory(subDirectory)) { if (ftpClient.makeDirectory(subDirectory)) { ftpClient.changeWorkingDirectory(subDirectory); } else { System.out.println("创建目录失败"); return UploadStatus.Create_Directory_Fail; } } start = end + 1; end = directory.indexOf("/", start); // 检查所有目录是否创建完毕 if (end <= start) { break; } } } } String remoteFileNameFormat = new String(remoteFileName.getBytes("GBK"),"iso-8859-1"); // 检查远程是否存在文件 FTPFile[] files = ftpClient.listFiles(remoteFileName); if (files.length == 1) { if (ftpClient.storeFile(remoteFileNameFormat,is)) { result = UploadStatus.Upload_New_File_Success; } else { result = UploadStatus.Upload_New_File_Failed; } is.close(); } else { if (ftpClient.storeFile(remoteFileNameFormat,is)) { result = UploadStatus.Upload_New_File_Success; } else { result = UploadStatus.Upload_New_File_Failed; } is.close(); } return result; } /** * 断开与远程服务器的连接 * * @throws IOException */ public void disconnect() throws IOException { if (ftpClient.isConnected()) { ftpClient.disconnect(); } } /** * 创建文件夹 * * @param remote * @param ftpClient * @return * @throws IOException */ public UploadStatus CreateDirecroty(String remote) throws IOException { UploadStatus status = UploadStatus.Create_Directory_Success; String directory = remote.substring(0, remote.lastIndexOf("/") + 1); if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory)) { int start = 0; int end = 0; if (directory.startsWith("/")) { start = 1; } else { start = 0; } end = directory.indexOf("/", start); while (true) { String subDirectory = remote.substring(start, end); if (!ftpClient.changeWorkingDirectory(subDirectory)) { if (ftpClient.makeDirectory(subDirectory)) { ftpClient.changeWorkingDirectory(subDirectory); } else { System.out.println("创建文件夹失败"); return UploadStatus.Create_Directory_Fail; } } start = end + 1; end = directory.indexOf("/", start); if (end <= start) { break; } } } return status; } }