由于要用APPLET实现大文件FTP上传下载,从网上搜索了几下,找到很多资料,最后决定采用基于 org.apache.commons.net.ftp包实现FTP上传下载,Net包中的类既提供对协议的底层访问也有高层的抽象。在大多数情况下,抽 象是足够的,它可以使你不必编写解析各种协议的底层套接字的代码。使用抽象不会损失任何功能。

借此感叹,org.apache.commons开源包真是森罗万象,应有尽有。反观国内打着开源旗号的软件也不少,但没几个能在当前软林扬名立万的,借山本赵一句经典台词:悲哀 悲哀 真是悲哀。

开发环境:winxp+eclipse3.2.2+struts2.0+jse5.0

最早采用以下代码:

package yp;

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 java.util.ArrayList;

import java.util.List;

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.FTPFile;

import org.apache.commons.net.ftp.FTPReply;

public class ContinueFTP{

private File file=null;

//是否完整保留原文件名

private boolean isSaveFileName = true;

//枚举上传状态

public enum UploadStatus {

Create_Directory_Fail,      //远程服务器相应目录创建失败

Create_Directory_Success,   //远程服务器创建目录成功

Upload_New_File_Success,    //上传新文件成功

Upload_New_File_Failed,     //上传新文件失败

File_Exits,                 //文件已经存在

Remote_Bigger_Local,        //远程文件大于本地文件

Upload_From_Break_Success,  //断点续传成功

Upload_From_Break_Failed,   //断点续传失败

Delete_Remote_Faild;        //删除远程文件失败

}

//枚举下载状态

public enum DownloadStatus {

Remote_File_Noexist,    //远程文件不存在

Local_Bigger_Remote,    //本地文件大于远程文件

Download_From_Break_Success,    //断点下载文件成功

Download_From_Break_Failed,     //断点下载文件失败

Download_New_Success,           //全新下载文件成功

Download_New_Failed;            //全新下载文件失败

}

public void init(){

}

public FTPClient ftpClient = new FTPClient();

public ContinueFTP(){

//设置将过程中使用到的命令输出到控制台

this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));

}

public String getRemoteFileName(String localFileName){

String fileName ="";

//分隔符

String sepaRator="\";

if (localFileName.indexOf(sepaRator)<0)

sepaRator="/";

//最后分隔符位置

int idx = localFileName.lastIndexOf(sepaRator)+1;

fileName = localFileName.substring(idx);

return fileName;

}

public boolean isFileExist(String remoteFileName) throws IOException{

boolean isFileExist = false;

//检查远程是否存在文件

FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1"));

if(files!=null && files.length >= 1){

isFileExist = true;

}

return isFileExist;

}

public boolean connect(String hostname,int port,String username,String password) throws Exception{

boolean bl = false;

try{

ftpClient.connect(hostname, port);

}catch(Exception e){

//可具体报错到主机和端口号

throw new BaseException("FTPConnError01",new String[]{"connect",e.getMessage()});

}

try{

//ftpClient.setControlEncoding("GBK");

if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){

if(ftpClient.login(username, password)){

bl = true;

}

}

}catch(Exception e){

//可具体报错到用户和密码

throw new BaseException("FTPConnError02",new String[]{"connect",e.getMessage()});

}

return bl;

}

public DownloadStatus download(String remote,String local) throws Exception{

//设置被动模式

ftpClient.enterLocalPassiveMode();

//设置以二进制方式传输

ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

DownloadStatus result;

//检查远程文件是否存在

FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"),"iso-8859-1"));

if(files.length != 1){

throw new BaseException("CellDataInputService",new String[]{"download","远程文件"+remote+"不存在"});

}

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(new String(remote.getBytes("GBK"),"iso-8859-1"));

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);

//TODO 更新文件下载进度,值存放在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(new String(remote.getBytes("GBK"),"iso-8859-1"));

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);

//TODO 更新文件下载进度,值存放在process变量中

}

}

in.close();

out.close();

boolean upNewStatus = ftpClient.completePendingCommand();

if(upNewStatus){

result = DownloadStatus.Download_New_Success;

}else {

result = DownloadStatus.Download_New_Failed;

}

}

return result;

}

public UploadStatus upload(File localFile,String remote) throws IOException{

//设置PassiveMode传输

ftpClient.enterLocalPassiveMode();

//设置以二进制流的方式传输

ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

//ftpClient.setControlEncoding("GBK");

UploadStatus result;

//对远程目录的处理

String remoteFileName = remote;

if(remote.contains("/")){

remoteFileName = remote.substring(remote.lastIndexOf("/")+1);

//创建服务器远程目录结构,创建失败直接返回

if(CreateDirecroty(remote, ftpClient)==UploadStatus.Create_Directory_Fail){

return UploadStatus.Create_Directory_Fail;

}

}

//检查远程是否存在文件

FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1"));

if(files!=null && files.length == 1){

long remoteSize = files[0].getSize();

//File f = new File(local);

long localSize = localFile.length();

if(remoteSize==localSize){

return UploadStatus.File_Exits;

}else if(remoteSize > localSize){

return UploadStatus.Remote_Bigger_Local;

}

//尝试移动文件内读取指针,实现断点续传

result = uploadFile(remoteFileName, localFile, ftpClient, remoteSize);

//如果断点续传没有成功,则删除服务器上文件,重新上传

if(result == UploadStatus.Upload_From_Break_Failed){

if(!ftpClient.deleteFile(remoteFileName)){

return UploadStatus.Delete_Remote_Faild;

}

result = uploadFile(remoteFileName, localFile, ftpClient, 0);

}

}else {

result = uploadFile(remoteFileName, localFile, ftpClient, 0);

}

return result;

}

public void disconnect() throws IOException{

if(this.ftpClient.isConnected()){

this.ftpClient.disconnect();

}

}

public String CreateDirecroty(String remoteDir)throws IOException{

String fillDir = "";

UploadStatus st = CreateDirecroty(remoteDir,this.ftpClient);

if (st == UploadStatus.Create_Directory_Success)

fillDir = remoteDir;

else

fillDir = "";

return fillDir;

}

public UploadStatus CreateDirecroty(String remote,FTPClient ftpClient) throws IOException{

UploadStatus status = UploadStatus.Create_Directory_Success;

String directory = remote.substring(0,remote.lastIndexOf("/")+1);

if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"),"iso-8859-1"))){

//如果远程目录不存在,则递归创建远程服务器目录

int start=0;

int end = 0;

if(directory.startsWith("/")){

start = 1;

}else{

start = 0;

}

end = directory.indexOf("/",start);

while(true){

String subDirectory = new String(remote.substring(start,end).getBytes("GBK"),"iso-8859-1");

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;

}

public UploadStatus uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throws IOException{

UploadStatus status;

//显示进度的上传

long step = localFile.length() / 100;

long process = 0;

long localreadbytes = 0L;

RandomAccessFile raf = new RandomAccessFile(localFile,"r");

OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"),"iso-8859-1"));

//断点续传

if(remoteSize>0){

ftpClient.setRestartOffset(remoteSize);

process = remoteSize /step;

raf.seek(remoteSize);

localreadbytes = remoteSize;

}

byte[] bytes = new byte[1024];

int c;

while((c = raf.read(bytes))!= -1){

out.write(bytes,0,c);

localreadbytes+=c;

//TODO 汇报上传状态

if(localreadbytes / step != process){

process = localreadbytes / step;

System.out.println("上传进度:" + process);

}

}

out.flush();

raf.close();

out.close();

boolean result =ftpClient.completePendingCommand();

if(remoteSize > 0){

status = result?UploadStatus.Upload_From_Break_Success:UploadStatus.Upload_From_Break_Failed;

}else {

status = result?UploadStatus.Upload_New_File_Success:UploadStatus.Upload_New_File_Failed;

}

return status;

}

public List<String> getRemoteFileList(String remoteDir){

List<String> list = new ArrayList<String>();

FTPFile[] files;

try {

files = ftpClient.listFiles(remoteDir);

for (int i = 0; i < files.length; i++) {

list.add(files[i].getName());

}

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

return list;

}

public boolean deleteFile(String fillFileName) throws Exception {

boolean bl = false;

this.ftpClient.deleteFile(fillFileName);

int status = this.ftpClient.getReplyCode();

if(status == 250){

bl = true;

System.out.println("成功删除FTP服务器中文件:" + fillFileName);

}

return bl;

}

public boolean deleteDir(String remoteDir)throws Exception {

boolean isDel = false;

this.ftpClient.removeDirectory(remoteDir);

int status = this.ftpClient.getReplyCode();

if(status == 250){

isDel = true;

System.out.println("成功删除FTP服务器中目录:" + remoteDir);

}

return isDel;

}

public static void main(String[] args) throws Exception {

ContinueFTP myFtp = new ContinueFTP();

try {

long l1 = System.currentTimeMillis();

System.out.println("begin:"+ l1);

if (myFtp.connect("10.68.7.182", 21, "a", "a")) {

String mkDir = myFtp.CreateDirecroty("TTT/ccc/");

if (mkDir != null && !mkDir.trim().equals(""))

System.out.println("mkDir success:"+mkDir);

//myFtp.download( "/XA01B03H05/5.mp3",file,"0");

//myFtp.upload("/XA01B03H05/5.mp3", "/云台山.mpg");

//myFtp.delete_file("/tmp.txt");

//String str = new String("电视剧");

//myFtp.ftpClient.removeDirectory("/kkk/jk/");

//myFtp.ftpClient.makeDirectory(new String(str.getBytes("GBK"),"iso-8859-1"));

myFtp.disconnect();

long l2 = System.currentTimeMillis();

System.out.println("end:"+ l2);

System.out.println("remaining:"+(l2-l1));

}

} catch (IOException e) {

System.out.println("连接FTP出错:"+e.getMessage());

}

}

public File getFile() {

return file;

}

public void setFile(File file) {

this.file = file;

}

public boolean isSaveFileName() {

return isSaveFileName;

}

public void setSaveFileName(boolean isSaveFileName) {

this.isSaveFileName = isSaveFileName;

}

}

通过main函数测试效果也不错,还显示上传或下载进度,再写一个对应action及jsp实现ftp上传下载,不过我吃过一次大亏,本来web服务器是本机,我原来做的上传下载都没有问题,但web服务器不在本机,就报说找不到文件!

后来终于想明白了,系统还是web服务器上路径找文件,当然找不到。

难道通过浏览器访问本地资源就真的无解了吗?

当然不是,也在找了很多解决方案,各有所长,又各有短处.

1.使用表单直接提交

这个方案肯定是被弊掉的,人一多就可能拖跨服务器.

2.使用FLASH进行文件上传

这个方案也尝试过,不过据说AS3只支持100M左右的文件上传,大文件无法上传,不知道是不是这样?如果是这样的话,那么这个方案也将行不通了.使用FLASH进行文件上传相对而言开发不会太困难.

3.使用APPLET进行文件上传

使用APPLET开发文件上传控件,这个对于使用JAVA来进行开发的非常方便,因为我们项目就是使用JAVA的,不过APPLET有安全策略的问题,无 法读取客户端的问题.如果要,那么用户必须修改其java.policy文件,这对于用户来讲简直是不可能的.如果使用程序下载动态修改也会比较麻烦.其 实还有一个破解之法,就是采用数字证书。

缺点:1)、客户端必须安装JRE;2)、想办法突破APPLET有安全策略的问题

优点:java编写,支持多浏览器

4.使用ACTIVEX进行文件上传

这是我目前认为比较可行的方式,而且网上也有很多类似这样的控件,但是都不是免费的,所以只能自己想办法解决了.使用ACTIVEX开发,可以使用C++、DELPHI等来进行开发

缺点:1>客户端推荐IE;2>IE安全设置中启用activex控件

优点:ACTIVEX开发速度快、界面友好

以下方案先采用第三种方案---Java applet,当年让Java 大火了一把的号称与微软的ActiveX 相提并论的技术当然,现在Java 出了JavaFX,是不是Applet 的替代品呢?你猜,猜不着呀?你再猜^_^

applet实现大文件ftp上传(一)相关推荐

  1. applet实现大文件ftp上传(三)

    下一步呢,当然就是对这个jar文件进行数字证书包装.流程如下: <1>.生成密匙证书(key certificate),该证书将存储在你的.keystore文件中.Validity指的是密 ...

  2. ACTIVEX实现大文件FTP上传下载---上

    ACTIVEX实现大文件FTP上传 在Windows 操作系统下,有一个重要的机制,就是OLE ,就是可以让某个应用程序(OLE Controller)访问其它应用程序(OLE Server)所提供的 ...

  3. Akka实战:HTTP大文件断点上传、下载,秒传

    2019独角兽企业重金招聘Python工程师标准>>> 访问:https://github.com/yangbajing/scala-applications/tree/master ...

  4. 大文件分片上传,断点续传,秒传 实现

    前段时间做视频上传业务,通过网页上传视频到服务器. 视频大小 小则几十M,大则 1G+,以一般的HTTP请求发送数据的方式的话,会遇到的问题:1,文件过大,超出服务端的请求大小限制:2,请求时间过长, ...

  5. jquery 分片上传php,php 大文件分片上传

    前端部分 上传 //上传控件 uploadBig('upload','zip,rar,7z,tar',{ id: '', type: 'upload_file', } ,(res)=>{ //t ...

  6. php带截切图片上传_PHP大文件切割上传并带进度条功能示例

    本文实例讲述了PHP大文件切割上传并带进度条功能.分享给大家供大家参考,具体如下: 前面一篇介绍了PHP大文件切割上传功能,这里再来进一步讲解PHP大文件切割上传并带进度条功能. 项目结构图: 14- ...

  7. 大文件分片上传前端框架_js实现大文件分片上传的方法

    文件夹上传:从前端到后端 文件上传是 Web 开发肯定会碰到的问题,而文件夹上传则更加难缠.网上关于文件夹上传的资料多集中在前端,缺少对于后端的关注,然后讲某个后端框架文件上传的文章又不会涉及文件夹. ...

  8. html video 设置进度条不可拖动_PHP大文件切割上传并带上进度条功能,不妨一试...

    文章来自:脚本之家链接:https://www.jb51.net/article/164316.htm 作者:hhmp 商务合作:请加微信(QQ):2230304070 资源教程分享 码农网-技术教程 ...

  9. 大文件分片上传前端框架_基于Node.js的大文件分片上传

    基于Node.js的大文件分片上传 我们在做文件上传的时候,如果文件过大,可能会导致请求超时的情况.所以,在遇到需要对大文件进行上传的时候,就需要对文件进行分片上传的操作.同时如果文件过大,在网络不佳 ...

最新文章

  1. 新视界,你好!_只愿与一人十指紧扣_新浪博客
  2. (转)Go语言核心36讲之Go语言入门基础知识
  3. Python魔法函数
  4. Google cpp style guide 之 include
  5. SQL注入之union联合注入——sql-lab第一关(非常非常详细的过程)
  6. 【工业控制】UV打印机喷头波形和墨水关系
  7. PAT (Basic Level) 1044 火星数字(模拟)
  8. wxpython收费吗_wxPython 使用总结
  9. 工业以太网交换机与网络交换机的区别
  10. PostgreSQL 逻辑订阅 - 给业务架构带来了什么希望?
  11. mysql 统一字符编码
  12. .NET基础 (08)字符串处理
  13. java ant教程_ant教程(三) ant入门
  14. Codeforces Round #542(Div. 2) B.Two Cakes
  15. Scala实现冒泡排序、归并排序和快速排序
  16. mysql 查询商品列表 显示tag_008商城项目:商品列表查询-查出商品并且分页
  17. Linux 运维工程师 必掌握的技能 ?
  18. windows文件自动同步
  19. UI控件Telerik UI for Silverlight发布R2 2019|附下载
  20. JUCE框架教程(3)—— Component ClassGraphics入门

热门文章

  1. 奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)
  2. Java面向对象进阶
  3. 蒙特卡罗方法求一个三维积分(论坛帮顶)
  4. java继承的举例_java继承实例
  5. 大数据职业理解_到底什么是大数据,大数据职业的具体工作内容是什么?
  6. c++语言程序的结构特点,C++的特点(特性)
  7. python语句解释_深入理解python with 语句
  8. mysql rename table_Mysql: RENAME TABLE IF EXISTS
  9. jpa 自定义sql if_mybatis仿jpa 使用@createDate @updateDate
  10. win10改计算机用户名,win10系统修改本地账号用户名的操作方法