【FTP】FTP文件上传下载-支持断点续传
- Jar包:apache的commons-net包;
- 支持断点续传
- 支持进度监控(有时出不来,搞不清原因)
相关知识点
- 编码格式: UTF-8等;
- 文件类型: 包括[BINARY_FILE_TYPE(常用)]和[ASCII_FILE_TYPE]两种;
- 数据连接模式:一般使用LocalPassiveMode模式,因为大部分客户端都在防火墙后面;
- 系统类型:UNIX/WINDOWS等,默认为Unix
流程
- 步骤1: 创建FTPClient对象,设置ftpClient属性:如编码格式、连接超时、文件上传下载进度监听器等;
- 步骤2: 使用ftpClient连接远程server:connect();
- 步骤3: 获取connect()的返回码getReplyCode(),判断是否连接成功:isPositiveCompletion();
- 步骤4: 登录远程server:login(),并转到相应目录,必要时要递归创建目录;
- 步骤5: 设置ftpClient属性:如缓存大小、文件类型、超时时间、数据连接模式等;
- 步骤6: ftp相关操作:如文件上传、下载等;
- 步骤7: 断开连接,释放资源:logout()/disconnect();
程序
FTP连接和登录
文件上传

文件下载
测试程序
完整程序
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;}@Overridepublic void bytesTransferred(CopyStreamEvent event) {bytesTransferred(event.getTotalBytesTransferred(),event.getBytesTransferred(), event.getStreamSize());}//totalBytesTransferred:当前总共已传输字节数;//bytesTransferred:最近一次传输字节数@Overridepublic 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();}}
参考链接
【FTP】FTP文件上传下载-支持断点续传的更多相关文章
- FTP文件上传并支持断点续传(一)—— win10 本地环境 ftp站点构建
由于之前项目开发是采用是采用的FTP文件上传,就一直想学习,但由于FTP服务器是公司的,为了方便就像把本地变成ftp站点,其实很简单,但也有很多坑 这里简单介绍一下自己遇到的坑 一:开通本地的ftp权 ...
- PHP 大文件上传,支持断点续传,求具体方案、源码或者文件上传插件
文件夹数据库处理逻辑 publicclass DbFolder { JSONObject root; public DbFolder() { this.root = new JSONObject(); ...
- ftp实现文件上传(下载)
例子代码 package getUrlPic; import java.io.ByteArrayInputStream; import java.io.IOException; import java ...
- 转:【专题十一】实现一个基于FTP协议的程序——文件上传下载器
引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...
- Java实现FTP批量大文件上传下载篇1
本文介绍了在Java中,如何使用Java现有的可用的库来编写FTP客户端代码,并开发成Applet控件,做成基于Web的批量.大文件的上传下载控件.文章在比较了一系列FTP客户库的基础上,就其中一个比 ...
- Python 基于Python实现Ftp文件上传,下载
基于Python实现Ftp文件上传,下载 by:授客 QQ:1033553122 测试环境: Ftp客户端:Windows平台 Ftp服务器:Linux平台 Python版本:Python 2.7 ...
- 专题十一:实现一个基于FTP协议的程序——文件上传下载器
引言: 在这个专题将为大家揭开下FTP这个协议的面纱,其实学习知识和生活中的例子都是很相通的,就拿这个专题来说,要了解FTP协议然后根据FTP协议实现一个文件下载器,就和和追MM是差不多的过程的,相信 ...
- 【ABAP系列】SAP ABAP 实现FTP的文件上传与下载
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 实现FTP的文 ...
- HTTP文件上传服务器-支持超大文件HTTP断点续传的实现办法
最近由于笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传.笔者在以前的博客如何实现支持大文件的高性能HTTP文件上传服务器已经介绍了实现大文件上传的一些基本 ...
随机推荐
- 如何在Form++开源组态平台添加硬件采集接口
E-Form++是一套值得推荐的高品质开源C++矢量图形库,C++编程之所以异常困难,主要就是没有很专业的C++基础架构库有关.E-Form++的出现一定程度上填补了这个空白.是开发工控.监控.建模与 ...
- 将页面上的内容导出到Excel
<asp:Button ID="lkbExport" runat="server" Name="Save" Text="导出 ...
- UE4 中在 Actor 中动态 Create Component 与ChildActor 的 小笔记
Note:旧版本的UE4 的Attach 和12.13版本有些不一样 创建Component: UCpp_MyComponent* temp_imageCom = NewObject<UCpp_ ...
- SIP模块版本错误问题:the sip module implements API v??? but XXX module requires API v???
系统安装了python 2.7,继续安装PyQt4,于是依次下载sip.pyqt4源码进行安装.用以下代码测试: import PyQt4.QtGui 显示出错.错误信息:the sip module ...
- Linux下memcache的安装
memcache是高性能,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度.目前用memcache解决互联网上的大用户读取是非常流行的一种用法,在互联网企业中有着广泛的应用.关 ...
- 使用js实现input输入框的增加
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- HANA学习笔记1-搭建HANA学习环境
一 硬件环境 两台电脑,一台为服务器装跑HANA虚拟机,一台为客户端运行HANA_STUDIO 服务器:内存至少需要16G windows server 2003 64位 ...
- 【转】Xcode概览:调试应用程序
原文转自:http://www.cocoachina.com/ios/20141128/10358.html 本文由CocoaChina翻译组成员Creolophus(github主页)翻译自苹果官方 ...
- 批量过滤POST GET数据
if(get_magic_quotes_gpc()){ $_GET = stripslashes_array($_GET); $_POST = stripslashes_array($_POST); ...
- JS和Android交互
//本地webview写法 webview = (WebView) findViewById(R.id.webview); webview.loadUrl("http://192.168.1 ...