1、上传本地文件或文件夹到远程FTP服务器端的功能。

当用户在本地文件列表中选择想要上传的文件后,点击上传按钮,将本机上指定的文件上传到FTP服务器当前展现的目录,下图为上传子模块流程图

选择好要上传的文件或文件夹,点击“上传”按钮,会触发com.oyp.ftp.panel.local.UploadAction类的actionPerformed(ActionEvent e)方法,其主要代码如下

	/**
* 上传文件动作的事件处理方法
*/
public void actionPerformed(java.awt.event.ActionEvent evt) {
// 获取用户选择的多个文件或文件夹
int[] selRows = this.localPanel.localDiskTable.getSelectedRows();
if (selRows.length < 1) {
JOptionPane.showMessageDialog(this.localPanel, "请选择上传的文件或文件夹");
return;
}
// 获取FTP服务器的当前路径
String pwd = this.localPanel.frame.getFtpPanel().getPwd();
// 创建FTP当前路径的文件夹对象
FtpFile ftpFile = new FtpFile("", pwd, true);
// 遍历本地资源的表格
for (int i = 0; i < selRows.length; i++) {
Object valueAt = this.localPanel.localDiskTable.getValueAt(
selRows[i], 0); // 获取表格选择行的第一列数据
if (valueAt instanceof DiskFile) {
final DiskFile file = (DiskFile) valueAt;
// 获取本地面板类中的队列,该队列是LinkedList类的实例对象
Queue<Object[]> queue = this.localPanel.queue;
queue.offer(new Object[] { file, ftpFile });// 执行offer方法向队列尾添加对象
}
}
}

在com.oyp.ftp.panel.local.UploadThread线程类的run()方法,会判断上传队列是否有对象,如果有则调用其copyFile(File file, FtpFile ftpFile)方法实现上传文件的功能,上传完后刷新远程FTP文件管理的面板。其run()方法主要代码如下

	/**
* 线程的主体方法
*/
public void run() { // 线程的主体方法
while (conRun) {
try {
Thread.sleep(1000); // 线程休眠1秒
Queue<Object[]> queue = localPanel.queue; // 获取本地面板的队列对象
queueValues = queue.peek(); // 获取队列首的对象
if (queueValues == null) { // 如果该对象为空
continue; // 进行下一次循环
}
File file = (File) queueValues[0]; // 获取队列中的本队文件对象
FtpFile ftpFile = (FtpFile) queueValues[1]; // 获取队列中的FTP文件对象
if (file != null) {
selPath = file.getParent();
copyFile(file, ftpFile); // 调用递归方法上传文件
FtpPanel ftpPanel = localPanel.frame.getFtpPanel();
ftpPanel.refreshCurrentFolder(); // 刷新FTP面板中的资源
}
Object[] args = queue.peek();
// 判断队列顶是否为处理的上一个任务。
if (queueValues == null || args == null
|| !queueValues[0].equals(args[0])) {
continue;
}
queue.remove(); // 移除队列首元素
} catch (Exception e) {
e.printStackTrace();
}
}
}

其中调用的copyFile(File file, FtpFile ftpFile)方法代码如下

        /**
* 上传线程的递归方法,上传文件夹的所有子文件夹和内容
* @param file
* - FTP文件对象
* @param localFolder
* - 本地文件夹对象
*/
private void copyFile(File file, FtpFile ftpFile) { // 递归遍历文件夹的方法
// 判断队列面板是否执行暂停命令
while (localPanel.frame.getQueuePanel().isStop()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} Object[] args = localPanel.queue.peek();
// 判断队列顶是不是上一个处理的任务。
if (queueValues == null || args == null
|| !queueValues[0].equals(args[0]))
return;
try {
// System.out.println("selPath:"+selPath);
path = file.getParentFile().getPath().replace(selPath, "");
// System.out.println("path:"+path);
ftpFile.setName(path.replace("\\", "/"));
path = ftpFile.getAbsolutePath();
// System.out.println("ftpFile.getAbsolutePath():"+path);
if (file.isFile()) {
UploadPanel uploadPanel = localPanel.frame.getUploadPanel();//上传面板
String remoteFile = path + "/" + file.getName(); // 远程FTP的文件名绝对路径
// System.out.println("remoteFile:" + remoteFile);
double fileLength = file.length() / Math.pow(1024, 2);
ProgressArg progressArg = new ProgressArg(
(int) (file.length() / 1024), 0, 0);//进度参数
String size = String.format("%.4f MB", fileLength);
Object[] row = new Object[] { file.getAbsoluteFile(), size,
remoteFile, ftpClient.getServer(), progressArg };
uploadPanel.addRow(row); //添加列
OutputStream put = ftpClient.put(remoteFile); // 获取服务器文件的输出流
FileInputStream fis = null; // 本地文件的输入流
try {
fis = new FileInputStream(file); // 初始化文件的输入流
} catch (Exception e) {
e.printStackTrace();
return;
}
int readNum = 0;
byte[] data = new byte[1024]; // 缓存大小
while ((readNum = fis.read(data)) > 0) { // 读取本地文件到缓存
Thread.sleep(0, 30); // 线程休眠
put.write(data, 0, readNum); // 输出到服务器
progressArg.setValue(progressArg.getValue() + 1);// 累加进度条
}
progressArg.setValue(progressArg.getMax()); // 结束进度条
fis.close(); // 关闭文件输入流
put.close(); // 关闭服务器输出流
} else if (file.isDirectory()) {
path = file.getPath().replace(selPath, "");
ftpFile.setName(path.replace("\\", "/"));
// System.out.println("Dirpath:"+path);
/**将目录切换到当前FTP服务器的当前目录*/
ftpClient.cd(this.localPanel.frame.getFtpPanel().getPwd()); // /media目录
/**
* 如果有创建文件夹的权限,则在当前FTP服务器的当前目录下创建文件夹
* 必须要有创建文件夹的权限,否则会报错
* path:audio
ftpFile.getAbsolutePath():/media/audio
remoteFile:/media/audio/梁静茹-会呼吸的痛Live.mp3
*/
ftpClient.sendServer("MKD " + path + "\r\n"); //创建 /media/audio 目录
ftpClient.readServerResponse(); /***********************************************************
* 如果没有有创建文件夹的权限,则创建文件夹,因此FTP服务器的当前路径下不存在
* 那么将文件上传到此FTP服务器的当前路径下
*
* 如要上传C://audio目录(目录中有 梁静茹-会呼吸的痛Live.mp3 和 林宥嘉-心酸.mp3 两个文件)
* 到 FTP服务器上的 /media/ 目录下
* 因为FTP服务器上没有 /media/audio 目录,并且FTP服务器当前的目录为 /media
* 所以将 C://audio目录下的文件上传到了 /media目录下
* ftpFile.getAbsolutePath():/media/audio
remoteFile:/media/梁静茹-会呼吸的痛Live.mp3
remoteFile:/media/林宥嘉-心酸.mp3
*/
//创建一个文件夹对象,检查该文件是否存在
File fileRemote=new File(this.localPanel.frame.getFtpPanel().getPwd()+path); //path:audio
//该目录不存在
if (!fileRemote.exists()) {
path=this.localPanel.frame.getFtpPanel().getPwd();
}
/***********************************************************/ File[] listFiles = file.listFiles();
for (File subFile : listFiles) {
Thread.sleep(0, 50);
copyFile(subFile, ftpFile);
}
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
System.exit(0);
// JOptionPane.showMessageDialog(localPanel, e1.getMessage());
} catch (Exception ex) {
ex.printStackTrace();
}
}

2、下载远程FTP服务器端的文件或文件夹到本地

当用户在远程FTP服务器文件列表中选择想要下载的文件后,点击下载按钮,将服务器上的文件下载至本机,下图为下载子模块流程图。

选择好要下载的文件或文件夹,点击“下载”按钮,会触发com.oyp.ftp.panel.ftp.DownAction类的actionPerformed(ActionEvent e)方法,其主要代码如下

        /**
* 下载按钮的动作处理器动作的事件处理方法
*/
@Override
public void actionPerformed(ActionEvent e) {
// 获取FTP资源表格的所有选择行
final int[] selRows = ftpPanel.ftpDiskTable.getSelectedRows();
if (selRows.length < 1)
return;
// 遍历表格的所有选择行
for (int i = 0; i < selRows.length; i++) {
// 获取每行的第一个单元值并转换成FtpFile类的对象
final FtpFile file = (FtpFile) ftpPanel.ftpDiskTable.getValueAt(
selRows[i], 0);
if (file != null) {
// 获取本地资源管理面板的当前文件夹
File currentFolder = ftpPanel.frame.getLocalPanel()
.getCurrentFolder();
// 把FTP文件对象和本地当前文件夹对象定义成数组添加到下载队列中
ftpPanel.queue.offer(new Object[] { file, currentFolder });
}
}
}

在com.oyp.ftp.panel.ftp.DownThread线程类的run()方法,会判断下载队列是否有对象,如果有则调用其downFile(FtpFile file, File localFolder)方法实现上传文件的功能,上传完后刷新远程FTP文件管理的面板。其run()方法代码如下

	public void run() { // 线程业务方法
while (conRun) {
try {
Thread.sleep(1000);
ftpClient.noop();
queueValues = ftpPanel.queue.peek();
if (queueValues == null) {
continue;
}
FtpFile file = (FtpFile) queueValues[0];
File localFolder = (File) queueValues[1];
if (file != null) {
path = file.getPath();
ftpClient.cd(path);
downFile(file, localFolder);
path = null;
ftpPanel.frame.getLocalPanel().refreshCurrentFolder();
}
Object[] args = ftpPanel.queue.peek();
// 判断队列顶是否为处理的上一个任务。
if (queueValues == null || args == null
|| !queueValues[0].equals(args[0]))
continue;
ftpPanel.queue.poll();
} catch (Exception e) {
e.printStackTrace();
}
}
}

其中调用的downFile(FtpFile file, File localFolder)方法代码如下

	/**
* 下载线程的递归方法,用户探索FTP下载文件夹的所有子文件夹和内容
* @param file FTP文件对象
* @param localFolder 本地文件夹对象
*/
private void downFile(FtpFile file, File localFolder) {
// 判断队列面板是否执行暂停命令
while (ftpPanel.frame.getQueuePanel().isStop()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object[] args = ftpPanel.queue.peek();
// 判断队列顶是否为处理的上一个任务。
if (queueValues == null || args == null
|| !queueValues[0].equals(args[0]))
return;
try {
String ftpFileStr = file.getAbsolutePath().replaceFirst(path + "/",
"");
if (file.isFile()) {
// 获取服务器指定文件的输入流
TelnetInputStream ftpIs = ftpClient.get(file.getName());
if (ftpIs == null) {
JOptionPane.showMessageDialog(this.ftpPanel, file.getName()
+ "无法下载");
return;
}
// 创建本地文件对象
File downFile = new File(localFolder, ftpFileStr);
// 创建本地文件的输出流
FileOutputStream fout = new FileOutputStream(downFile, true);
// 计算文件大小
double fileLength = file.getLongSize() / Math.pow(1024, 2);
ProgressArg progressArg = new ProgressArg((int) (file
.getLongSize() / 1024), 0, 0); //进度参数
String size = String.format("%.4f MB", fileLength);
//"文件名", "大小", "本地文件名","主机", "状态"
Object[] row = new Object[] { ftpFileStr, size,
downFile.getAbsolutePath(), ftpClient.getServer(),
progressArg };
DownloadPanel downloadPanel = ftpPanel.frame.getDownloadPanel(); //下载队列面板
downloadPanel.addRow(row); //添加列
byte[] data = new byte[1024]; // 定义缓存
int read = -1;
while ((read = ftpIs.read(data)) > 0) { // 读取FTP文件内容到缓存
Thread.sleep(0, 30); // 线程休眠
fout.write(data, 0, read); // 将缓存数据写入本地文件
// 累加进度条
progressArg.setValue(progressArg.getValue() + 1);
}
progressArg.setValue(progressArg.getMax());// 结束进度条
fout.close(); // 关闭文件输出流
ftpIs.close(); // 关闭FTP文件输入流
} else if (file.isDirectory()) { // 如果下载的是文件夹
// 创建本地文件夹对象
File directory = new File(localFolder, ftpFileStr);
directory.mkdirs(); // 创建本地的文件夹
ftpClient.cd(file.getName()); // 改变FTP服务器的当前路径
// 获取FTP服务器的文件列表信息
TelnetInputStream telnetInputStream=ftpClient.list();
byte[]names=new byte[2048];
int bufsize=0;
bufsize=telnetInputStream.read(names, 0, names.length);
int i=0,j=0;
while(i<bufsize){
//字符模式为10,二进制模式为13
// if (names[i]==10) {
if (names[i]==13) {
//获取字符串 -rwx------ 1 user group 57344 Apr 18 05:32 腾讯电商2013实习生招聘TST推荐模板.xls
//文件名在数据中开始做坐标为j,i-j为文件名的长度,文件名在数据中的结束下标为i-1
String fileMessage = new String(names,j,i-j);
if(fileMessage.length() == 0){
System.out.println("fileMessage.length() == 0");
break;
}
//按照空格将fileMessage截为数组后获取相关信息
// 正则表达式 \s表示空格,{1,}表示1一个以上
if(!fileMessage.split("\\s+")[8].equals(".") && !fileMessage.split("\\s+")[8].equals("..")){
/**文件大小*/
String sizeOrDir="";
if (fileMessage.startsWith("d")) {//如果是目录
sizeOrDir="<DIR>";
}else if (fileMessage.startsWith("-")) {//如果是文件
sizeOrDir=fileMessage.split("\\s+")[4];
}
/**文件名*/
String fileName=fileMessage.split("\\s+")[8];
FtpFile ftpFile = new FtpFile();
// 将FTP目录信息初始化到FTP文件对象中
ftpFile.setSize(sizeOrDir);
ftpFile.setName(fileName);
ftpFile.setPath(file.getAbsolutePath());
// 递归执行子文件夹的下载
downFile(ftpFile, localFolder);
}
// j=i+1;//上一次位置为字符模式
j=i+2;//上一次位置为二进制模式
}
i=i+1;
}
ftpClient.cdUp(); // 返回FTP上级路径
}
} catch (Exception ex) {
ex.printStackTrace();
}
}

==================================================================================================

  作者:欧阳鹏  欢迎转载,与人分享是进步的源泉!

  转载请保留原文地址:http://blog.csdn.net/ouyang_peng

==================================================================================================

Java语言实现简单FTP软件------>上传下载管理模块的实现(十一)的更多相关文章

  1. Java语言实现简单FTP软件------>上传下载队列窗口的实现(七)

    1.首先看一下队列窗口的界面 2.看一下上传队列窗口的界面 3.看一下下载队列窗口的界面 4.队列窗口的实现 package com.oyp.ftp.panel.queue; import stati ...

  2. Java语言实现简单FTP软件------>源码放送(十三)

    Java语言实现简单FTP软件------>FTP协议分析(一) Java语言实现简单FTP软件------>FTP软件效果图预览之下载功能(二) Java语言实现简单FTP软件----- ...

  3. Java语言实现简单FTP软件------>FTP软件主界面的实现(四)

    首先看一下该软件的整体代码框架                        1.首先介绍程序的主入口FTPMain.java,采用了一个漂亮的外观风格 package com.oyp.ftp; im ...

  4. 使用ftp软件上传下载php文件时换行丢失bug

    正 文:   在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下notepad++编辑器写好的php文件,在使用ftp上传到linux服务器后,php文件的换行符全部丢失了, ...

  5. 使用ftp软件上传下载php文件时换行丢失bug(全部变为一行)

    文章来源:http://www.piaoyi.org/computer/ftp-php-r-n-bug.html 正 文: 在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下 ...

  6. ****使用ftp软件上传下载php文件时换行符丢失bug

    在使用ftp软件上传下载php源文件时,我们偶尔会发现在本地windows下notepad++编辑器写好的php文件,在使用ftp上传到linux服务器后,php文件的换行符全部丢失了,导致php文件 ...

  7. Java语言实现简单FTP软件------>FTP软件效果图预览之下载功能(二)

    介绍完FTP协议后,来看看该软件完成后的效果图 客户端的主界面如上图所示,主要是分为以下几个界面: 数据输入界面:用来让用户输入服务器的地址,用户名,密码,端口号等. 站点菜单.本地菜单.远程菜单以及 ...

  8. Java语言实现简单FTP软件------>辅助功能模块FTP站点管理的实现(十二)

    1.FTP站点管理 点击"FTP站点管理"按钮,弹出对话框"FTP站点管理",如下图 1) 连接站点 在FTP站点管理面板上选好要连接的站点,点击"连 ...

  9. Java语言实现简单FTP软件------>FTP软件本地窗口的实现(五)

    1.首先看一下本地窗口的布局效果 2.看一下本地窗口实现的代码框架 2.本地窗口的具体实现代码LocalPanel.java package com.oyp.ftp.panel.local; impo ...

随机推荐

  1. Hibernate级联及控制反转的增删改查

    在JavaHibernate中,双向多对一的操作一直是一个重点难点,本篇文章就是来探讨这个问题. 双向多对一:一个班级对应多个学生,多个学生同属于一个班级,通过班级信息可以查到班级内的学生,通过学生可 ...

  2. OpenCV2学习笔记(十五):利用Cmake高速查找OpenCV函数源代码

    在使用OpenCV时,在对一个函数的调用不是非常了解的情况下,通常希望查到该函数的官方声明.而假设想进一步研究OpenCV的函数,则必须深入到源码. 在VS中我们能够选中想要查看的OpenCV函数,点 ...

  3. 倍福TwinCAT(贝福Beckhoff)基础教程 松下伺服驱动器报错 88怎么办

    请确认在TWINCAT在线模式下,把Drive的Modes of operation改为8       更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com ...

  4. 为什么要上大四???why

    毕业证        即将要上大四了.近期一直在思考,毕业证对于我有什么作用呢?我从来不忌讳表露自己的观点.哪怕这个观点是错误的. 如今这个观点,想必又要激起无数人对我的责骂吧?        但是毕 ...

  5. 【BIEE】10_资料库查看数据报错

    导入元数据后,在资料库右键物理表名,[查看数据]报错: 出现这个问题,没搞明白是为啥- 后来百度意外发现一个方法,修改NQSConfig.INI文件即可解决问题 那么就开始来搞定这个问题 [1]打开路 ...

  6. 【VBA】切换引用样式

    在Excle中有两种引用方式,例如:第一行第一列的单元格可以是:A1  也可以是R1C1 切换引用样式的代码如下: Sub 切换引用样式() Application.ReferenceStyle = ...

  7. Ubuntu 12.04 的IP 设置

      通过访问 /etc/network/interfaces 实现动态IP 或者静态IP 的设置. vim /et/network/interfaces 1.设置动态IP auto lo iface ...

  8. java检测http请求的ip地址 Java问题通用解决代码

    以后再用到的话,至少能起个参考作用 java实现,struts2的Action中,依赖HttpServletRequest     package net.dookoo.web.action;   i ...

  9. 【SpringMVC学习08】SpringMVC中实现文件上传

    之前有写过一篇struts2实现的文件上传,这一篇博文主要来总结下springmvc实现文件上传的步骤.首先来看一下单个文件的上传,然后再来总结下多个文件上传. 1. 环境准备 springmvc上传 ...

  10. mysqldumpslow命令

    mysqldumpslow --help显示如下 Parse and summarize the MySQL slow query log. Options are --verbose verbose ...