【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文件上传服务器已经介绍了实现大文件上传的一些基本 ...
随机推荐
- WPF(WP7、WP8)实现圆形图片
在WP平台上制作图片圆角其实特别简单, 用Image控件的Clip属性即可(RadiusX-Y设置为图片尺寸的一半) <Image Source="{Binding photo}&qu ...
- CSS3 实现3D旋转木马效果
基本原理: 1.首先我们需要让图片能旋转的效果,我们让所有图片绝对定位(position:absolute),共用一个中心点. 2.对于舞台我们加一个视距,比如下面的demo是 perspective ...
- Razor视图引擎-基础语法
所有以 @开头 或 @{ /* 代码体 */ } (在@与{直接不得添加任何空格) 的部分代码都会被ASP.NET引擎进行处理. 在 @{ /*代码体*/ } 内的代码每一行都必须以";& ...
- textarea自适应高度
最近做项目遇见了这个自适应高度的问题,也在网上找了些资料,大多选择用DIV模拟textarea,但是这样就有安全性的问题,因为你是可以直接将HTML代码输入进去的. 接下来介绍的这种办法是采用两个te ...
- 【转】CSS设置DIV背景色渐变显示
[原链接]http://www.2cto.com/kf/201310/248187.html <style type="text/css"> .linear{ ...
- printf函数
printf函数的格式及含义 d 以十进制带符号的形式输出整数(对正数不输出符号) o 以八进制无符号的形式输出整数(不输出 ...
- python ABC
因为项目需要,总是会有各种各样要重命名文件的场合,manual的方法当然不可取,bat的方法又感觉不够强大,所以就从零开始学python,就为了能够自动批量修改文件名,倒腾了一个周六,总算可以了 :) ...
- 【转载】ANSYS TRANSIENT ANSLYSIS [2]
原文地址:http://sps.utm.my/wp-content/uploads/2014/12/ANSYS-day2-Transient-analysis.pdf
- python 3 学习笔记(一)
由于之前学过python2,因此今天就想记录下第一天学习python3过程中的遇到的不同和之前没有太掌握的基础知识. python2和python3的语法区别 print语句 在Python2里,pr ...
- java.lang.NoSuchMethodError: antlr.collections.AST.getLine()I错误解决
在J2EE框架下开发web网站,这种问题经常遇到,只要我们网上搜一下,就可以看到很多版本的,我整理一下: 第一种可能性解决:看看我的项目:主要 是里面的Structs 1.3 (structs 2)和 ...