关键词:
- 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支持ie低版本的上传大文件切割上传断点续传秒传
...swfupload2、http://download.csdn.net/detail/rememberme001/9873136支持大文件传输,先把大文件分割成每个2M的小文件分批上传,再组合成一个大文件。支持断点续传,MD5校验实现妙传功能,支 查看详情
超大文件上传和断点续传的组件
...、概述 所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载。在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了。一般断点下载时才用到Range和Content-Range实体头。HTTP协议本身不支持断点... 查看详情
html5大文件断点续传完整思路整理
...继续传输。关闭浏览器后保留进度信息。支持文件夹批量上传下载,服务器端保留文件夹层级结构, 查看详情
文件下载之断点续传(客户端与服务端的实现)
【转】文件下载之断点续传(客户端与服务端的实现)【转】文件下载之断点续传(客户端与服务端的实现)前面讲了文件的上传,今天来聊聊文件的下载。老规矩,还是从最简单粗暴的开始。那么多简单算简单?多粗暴算粗暴... 查看详情
解决php超大文件下载,断点续传下载的方法详解
一、功能性及非功能性需求:文件批量下载,支持断点续传。支持批量下载1000个文件。使用JS能够实现批量下载,能够提供接口从指定url中下载文件并保存在本地指定路径中。服务器不需要打包。支持大文件断点下载。比如下载... 查看详情
完整版断点续传秒传,支持超大大大文件_支持重定义文件名和路径
...继续传输。关闭浏览器后保留进度信息。支持文件夹批量上传下载,服务器端保留文件夹层级结构,服务器端文件夹层级结构与本地相同。支持断点续传,关闭浏览器或刷新浏览器后仍然能够保留进度。支持文件夹结构管理,支... 查看详情
b/s之大文件分段上传断点续传
4GB以上超大文件上传和断点续传服务器的实现随着视频网站和大数据应用的普及,特别是高清视频和4K视频应用的到来,超大文件上传已经成为了日常的基础应用需求。但是在很多情况下,平台运营方并没有大文件上传和断点续... 查看详情
文件上传控件-如何上传文件-大文件断点续传
需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在20G内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以20G来进行限制。PC端全平台支持,要求支持Windows,Mac,Linux支持所有浏览器... 查看详情
java文件下载,支持任务暂停,恢复,断点续传;任务状态查询;任务并发控制(代码片段)
大文件上传服务器支持超大文件http断点续传实践总结
...笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传。这里在简要归纳一下,方便记忆:服务器端由C语言实现,而不是 查看详情
大文件上传服务器支持超大文件http断点续传实践总结(代码片段)
...笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传。这里在简要归纳一下,方便记忆:服务器端由C语言实现,而不是用java、PHP这种解释型语言来实现 查看详情
大文件上传服务器支持超大文件http断点续传实践总结(代码片段)
...笔者所在的研发集团产品需要,需要支持高性能的大文件http上传,并且要求支持http断点续传。这里在简要归纳一下,方便记忆:服务器端由C语言实现,而不是 查看详情
文件下载之断点续传(客户端与服务端的实现)
...:http://www.cnblogs.com/zhaopei/p/download.html 阅读目录 文件下载-服务端使用a标签提供文件下载使用Response.TransmitFile提供文件下载其他方式文件下载文件下载-客户端直接下载异步下载断点续传断点续传(服务端的支持)多线程同时... 查看详情
php断点续传之文件上传与文件下载(代码片段)
下载:<?php/**php下载类,支持断点续传*Date:2013-06-30*Author:fdipzone*Ver:1.0**Func:*publicdownload:下载文件*publicsetSpeed:设置下载速度*privategetRange:获取header中Range*/classFileDownload//classstartprivate$_speed=512;// 查看详情
rsync支持断点续传文件
参考:https://my.oschina.net/ccLlinux/blog/1859116基本命令:rsync[OPTION]…SRC(需要备份的原文件)DEST(Push的位置)example:download:rsync-avuser@hostip:/scratch/test/test_sh.sh/Users/username/test/test.sh上传:rsync-av/Users/u 查看详情
断点续传下载原理实现
需求背景动态创建的文件下载的时候希望浏览器显示下载进度动态创建的文件希望能够分段下载HTTP断点续传报文要实现HTTP断点续传必须要简单了解以下几个报文。Accept-Ranges告诉客户端(浏览器..)服务器端支持断点续传 服务... 查看详情
javascript之大文件分段上传断点续传
需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制。第一步:前端修改由于项目使用的是BJUI前端框架,并... 查看详情
java实现文件的断点续传
需求:项目要支持大文件上传功能,经过讨论,初步将文件上传大小控制在500M内,因此自己需要在项目中进行文件上传部分的调整和配置,自己将大小都以501M来进行限制。第一步:前端修改由于项目使用的是BJUI前端框架,并... 查看详情