Java語言實現(xiàn)簡單FTP軟件 FTP上傳下載管理模塊實現(xiàn)(11)
本文為大家分享了FTP上傳下載管理模塊的實現(xiàn)方法,供大家參考,具體內(nèi)容如下
1、上傳本地文件或文件夾到遠(yuǎn)程FTP服務(wù)器端的功能。
當(dāng)用戶在本地文件列表中選擇想要上傳的文件后,點擊上傳按鈕,將本機(jī)上指定的文件上傳到FTP服務(wù)器當(dāng)前展現(xiàn)的目錄,下圖為上傳子模塊流程圖

選擇好要上傳的文件或文件夾,點擊“上傳”按鈕,會觸發(fā)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服務(wù)器的當(dāng)前路徑
String pwd = this.localPanel.frame.getFtpPanel().getPwd();
// 創(chuàng)建FTP當(dāng)前路徑的文件夾對象
FtpFile ftpFile = new FtpFile("", pwd, true);
// 遍歷本地資源的表格
for (int i = 0; i < selRows.length; i++) {
Object valueAt = this.localPanel.localDiskTable.getValueAt(
selRows[i], 0); // 獲取表格選擇行的第一列數(shù)據(jù)
if (valueAt instanceof DiskFile) {
final DiskFile file = (DiskFile) valueAt;
// 獲取本地面板類中的隊列,該隊列是LinkedList類的實例對象
Queue<Object[]> queue = this.localPanel.queue;
queue.offer(new Object[] { file, ftpFile });// 執(zhí)行offer方法向隊列尾添加對象
}
}
}
在com.oyp.ftp.panel.local.UploadThread線程類的run()方法,會判斷上傳隊列是否有對象,如果有則調(diào)用其copyFile(File file, FtpFile ftpFile)方法實現(xiàn)上傳文件的功能,上傳完后刷新遠(yuǎn)程FTP文件管理的面板。其run()方法主要代碼如下
* 線程的主體方法
*/
public void run() { // 線程的主體方法
while (conRun) {
try {
Thread.sleep(1000); // 線程休眠1秒
Queue<Object[]> queue = localPanel.queue; // 獲取本地面板的隊列對象
queueValues = queue.peek(); // 獲取隊列首的對象
if (queueValues == null) { // 如果該對象為空
continue; // 進(jìn)行下一次循環(huán)
}
File file = (File) queueValues[0]; // 獲取隊列中的本隊文件對象
FtpFile ftpFile = (FtpFile) queueValues[1]; // 獲取隊列中的FTP文件對象
if (file != null) {
selPath = file.getParent();
copyFile(file, ftpFile); // 調(diào)用遞歸方法上傳文件
FtpPanel ftpPanel = localPanel.frame.getFtpPanel();
ftpPanel.refreshCurrentFolder(); // 刷新FTP面板中的資源
}
Object[] args = queue.peek();
// 判斷隊列頂是否為處理的上一個任務(wù)。
if (queueValues == null || args == null
|| !queueValues[0].equals(args[0])) {
continue;
}
queue.remove(); // 移除隊列首元素
} catch (Exception e) {
e.printStackTrace();
}
}
}
其中調(diào)用的copyFile(File file, FtpFile ftpFile)方法代碼如下
/**
* 上傳線程的遞歸方法,上傳文件夾的所有子文件夾和內(nèi)容
* @param file
* - FTP文件對象
* @param localFolder
* - 本地文件夾對象
*/
private void copyFile(File file, FtpFile ftpFile) { // 遞歸遍歷文件夾的方法
// 判斷隊列面板是否執(zhí)行暫停命令
while (localPanel.frame.getQueuePanel().isStop()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object[] args = localPanel.queue.peek();
// 判斷隊列頂是不是上一個處理的任務(wù)。
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(); // 遠(yuǎn)程FTP的文件名絕對路徑
// System.out.println("remoteFile:" + remoteFile);
double fileLength = file.length() / Math.pow(1024, 2);
ProgressArg progressArg = new ProgressArg(
(int) (file.length() / 1024), 0, 0);//進(jìn)度參數(shù)
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); // 獲取服務(wù)器文件的輸出流
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); // 輸出到服務(wù)器
progressArg.setValue(progressArg.getValue() + 1);// 累加進(jìn)度條
}
progressArg.setValue(progressArg.getMax()); // 結(jié)束進(jìn)度條
fis.close(); // 關(guān)閉文件輸入流
put.close(); // 關(guān)閉服務(wù)器輸出流
} else if (file.isDirectory()) {
path = file.getPath().replace(selPath, "");
ftpFile.setName(path.replace("\\", "/"));
// System.out.println("Dirpath:"+path);
/**將目錄切換到當(dāng)前FTP服務(wù)器的當(dāng)前目錄*/
ftpClient.cd(this.localPanel.frame.getFtpPanel().getPwd()); // /media目錄
/**
* 如果有創(chuàng)建文件夾的權(quán)限,則在當(dāng)前FTP服務(wù)器的當(dāng)前目錄下創(chuàng)建文件夾
* 必須要有創(chuàng)建文件夾的權(quán)限,否則會報錯
* path:audio
ftpFile.getAbsolutePath():/media/audio
remoteFile:/media/audio/梁靜茹-會呼吸的痛Live.mp3
*/
ftpClient.sendServer("MKD " + path + "\r\n"); //創(chuàng)建 /media/audio 目錄
ftpClient.readServerResponse();
/***********************************************************
* 如果沒有有創(chuàng)建文件夾的權(quán)限,則創(chuàng)建文件夾,因此FTP服務(wù)器的當(dāng)前路徑下不存在
* 那么將文件上傳到此FTP服務(wù)器的當(dāng)前路徑下
*
* 如要上傳C://audio目錄(目錄中有 梁靜茹-會呼吸的痛Live.mp3 和 林宥嘉-心酸.mp3 兩個文件)
* 到 FTP服務(wù)器上的 /media/ 目錄下
* 因為FTP服務(wù)器上沒有 /media/audio 目錄,并且FTP服務(wù)器當(dāng)前的目錄為 /media
* 所以將 C://audio目錄下的文件上傳到了 /media目錄下
* ftpFile.getAbsolutePath():/media/audio
remoteFile:/media/梁靜茹-會呼吸的痛Live.mp3
remoteFile:/media/林宥嘉-心酸.mp3
*/
//創(chuàng)建一個文件夾對象,檢查該文件是否存在
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、下載遠(yuǎn)程FTP服務(wù)器端的文件或文件夾到本地
當(dāng)用戶在遠(yuǎn)程FTP服務(wù)器文件列表中選擇想要下載的文件后,點擊下載按鈕,將服務(wù)器上的文件下載至本機(jī),下圖為下載子模塊流程圖。

選擇好要下載的文件或文件夾,點擊“下載”按鈕,會觸發(fā)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++) {
// 獲取每行的第一個單元值并轉(zhuǎn)換成FtpFile類的對象
final FtpFile file = (FtpFile) ftpPanel.ftpDiskTable.getValueAt(
selRows[i], 0);
if (file != null) {
// 獲取本地資源管理面板的當(dāng)前文件夾
File currentFolder = ftpPanel.frame.getLocalPanel()
.getCurrentFolder();
// 把FTP文件對象和本地當(dāng)前文件夾對象定義成數(shù)組添加到下載隊列中
ftpPanel.queue.offer(new Object[] { file, currentFolder });
}
}
}
在com.oyp.ftp.panel.ftp.DownThread線程類的run()方法,會判斷下載隊列是否有對象,如果有則調(diào)用其downFile(FtpFile file, File localFolder)方法實現(xiàn)上傳文件的功能,上傳完后刷新遠(yuǎn)程FTP文件管理的面板。其run()方法代碼如下
public void run() { // 線程業(yè)務(wù)方法
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();
// 判斷隊列頂是否為處理的上一個任務(wù)。
if (queueValues == null || args == null
|| !queueValues[0].equals(args[0]))
continue;
ftpPanel.queue.poll();
} catch (Exception e) {
e.printStackTrace();
}
}
}
其中調(diào)用的downFile(FtpFile file, File localFolder)方法代碼如下
/**
* 下載線程的遞歸方法,用戶探索FTP下載文件夾的所有子文件夾和內(nèi)容
* @param file FTP文件對象
* @param localFolder 本地文件夾對象
*/
private void downFile(FtpFile file, File localFolder) {
// 判斷隊列面板是否執(zhí)行暫停命令
while (ftpPanel.frame.getQueuePanel().isStop()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Object[] args = ftpPanel.queue.peek();
// 判斷隊列頂是否為處理的上一個任務(wù)。
if (queueValues == null || args == null
|| !queueValues[0].equals(args[0]))
return;
try {
String ftpFileStr = file.getAbsolutePath().replaceFirst(path + "/",
"");
if (file.isFile()) {
// 獲取服務(wù)器指定文件的輸入流
TelnetInputStream ftpIs = ftpClient.get(file.getName());
if (ftpIs == null) {
JOptionPane.showMessageDialog(this.ftpPanel, file.getName()
+ "無法下載");
return;
}
// 創(chuàng)建本地文件對象
File downFile = new File(localFolder, ftpFileStr);
// 創(chuàng)建本地文件的輸出流
FileOutputStream fout = new FileOutputStream(downFile, true);
// 計算文件大小
double fileLength = file.getLongSize() / Math.pow(1024, 2);
ProgressArg progressArg = new ProgressArg((int) (file
.getLongSize() / 1024), 0, 0); //進(jìn)度參數(shù)
String size = String.format("%.4f MB", fileLength);
//"文件名", "大小", "本地文件名","主機(jī)", "狀態(tài)"
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文件內(nèi)容到緩存
Thread.sleep(0, 30); // 線程休眠
fout.write(data, 0, read); // 將緩存數(shù)據(jù)寫入本地文件
// 累加進(jìn)度條
progressArg.setValue(progressArg.getValue() + 1);
}
progressArg.setValue(progressArg.getMax());// 結(jié)束進(jìn)度條
fout.close(); // 關(guān)閉文件輸出流
ftpIs.close(); // 關(guān)閉FTP文件輸入流
} else if (file.isDirectory()) { // 如果下載的是文件夾
// 創(chuàng)建本地文件夾對象
File directory = new File(localFolder, ftpFileStr);
directory.mkdirs(); // 創(chuàng)建本地的文件夾
ftpClient.cd(file.getName()); // 改變FTP服務(wù)器的當(dāng)前路徑
// 獲取FTP服務(wù)器的文件列表信息
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,二進(jìn)制模式為13
// if (names[i]==10) {
if (names[i]==13) {
//獲取字符串 -rwx------ 1 user group 57344 Apr 18 05:32 騰訊電商2013實習(xí)生招聘TST推薦模板.xls
//文件名在數(shù)據(jù)中開始做坐標(biāo)為j,i-j為文件名的長度,文件名在數(shù)據(jù)中的結(jié)束下標(biāo)為i-1
String fileMessage = new String(names,j,i-j);
if(fileMessage.length() == 0){
System.out.println("fileMessage.length() == 0");
break;
}
//按照空格將fileMessage截為數(shù)組后獲取相關(guān)信息
// 正則表達(dá)式 \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());
// 遞歸執(zhí)行子文件夾的下載
downFile(ftpFile, localFolder);
}
// j=i+1;//上一次位置為字符模式
j=i+2;//上一次位置為二進(jìn)制模式
}
i=i+1;
}
ftpClient.cdUp(); // 返回FTP上級路徑
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
功能效果圖可以查看以下兩篇文章。
Java語言實現(xiàn)簡單FTP軟件------>FTP軟件效果圖預(yù)覽之上傳功能(三)
Java語言實現(xiàn)簡單FTP軟件------>FTP軟件效果圖預(yù)覽之下載功能(二)
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
spring boot 實現(xiàn)阿里云視頻點播功能(刪除視頻)
這篇文章主要介紹了spring boot 實現(xiàn)阿里云視頻點播(刪除視頻功能),本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12
Springboot詳解線程池與多線程及阻塞隊列的應(yīng)用詳解
本例應(yīng)用線程池、多線程、阻塞隊列處理一個流程任務(wù)。本例處理一個訂單流程,主要包括生成訂單、訂單處理、訂單入庫,下面我們一起看看2022-06-06
java基本教程之java線程等待與java喚醒線程 java多線程教程
這篇文章主要介紹了對線程等待/喚醒方法,文中使用了多個示例,大家參考使用吧2014-01-01
Maven中optional和scope元素的使用弄明白了嗎
這篇文章主要介紹了Maven中optional和scope元素的使用弄明白了嗎,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12

