使用Commons net實現FTP上傳文件(網絡問題無響應解決方案)

       這段時間一直忙着項目開發,沒顧上寫總結。今天抽點時間對於之前遇到的ftp上傳文件無應答的問題總結一下,方便自己以後查看,也方便下個遇到此問題的人能夠快速的解決問題。

       使用Apache的開源框架寫的一個很簡單的ftp上傳的demo,如果網絡環境穩定的情況下上傳文件不會有問題,也能得到服務器文件傳完後的響應狀態,但是遇到大文件和網絡不好的情況下,上傳文件時間比較長(半個小時以上),這時執行ftpClient.storeFile("test.ts", in)這句代碼會卡在這裏,即使文件傳完了也不會做出響應,得不到服務器的響應代碼就不會繼續往下執行,線程也就會一直停在這裏。下面是一個簡單的文件ftp上傳demo:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

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

public class FtpUtil {

	public static void main(String[] args) {

		FTPClient ftpClient = new FTPClient();

		try {
			// 連接指定服務器,默認端口爲21
			ftpClient.connect("127.0.0.1");
			System.out.println("connect to server");

			// 獲取響應字符串(FTP服務器上可設置)
			String replyString = ftpClient.getReplyString();
			System.out.println("replyString: " + replyString);

			// 獲取響應碼用於驗證是否連接成功
			int reply = ftpClient.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				System.out.println(reply);
				System.exit(1);
			}

			// 設置鏈接編碼,windows主機UTF-8會亂碼,需要使用GBK或gb2312編碼
			ftpClient.setControlEncoding("GBK");

			// 登錄服務器
			boolean login = ftpClient.login("ceshi", "ceshi");
			if (login) {
				System.out.println("登錄成功!");
			} else {
				System.out.println("登錄失敗!");
			}

			// 獲取所有文件和文件夾的名字
			FTPFile[] files = ftpClient.listFiles();
			for (FTPFile file : files) {
				if (file.isDirectory()) {
					System.out.println(file.getName() + " 是文件夾");
				}
				if (file.isFile()) {
					System.out.println(file.getName() + " 是文件");
				}
			}

			// 生成InputStream用於上傳本地文件
			InputStream in = new FileInputStream("e:\\ceshi.txt");

			// 上傳文件
			boolean result = ftpClient.storeFile("test.txt", in);
			if (result) {
				System.out.println("上傳成功!");
			}
			in.close();

			// 註銷登錄
			boolean logout = ftpClient.logout();
			if (logout) {
				System.out.println("註銷成功!");
			} else {
				System.out.println("註銷失敗!");
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 關閉鏈接需要放在finally語句塊中
			if (ftpClient.isConnected()) {
				try {
					ftpClient.disconnect();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
解決方案

       遇到這樣的問題剛開始不知道怎麼回事,經過一番排查後找到了問題的原因,最後給出下面兩種解決方法。

       1、這個框架提供了多種上傳方法,比如:

org.apache.commons.net.ftp.FTPClient.appendFileStream(String remote) throwsIOException
org.apache.commons.net.ftp.FTPClient.appendFile(String remote,InputStream local) throws IOException
org.apache.commons.net.ftp.FTPClient.storeFileStream(String remote) throwsIOException
org.apache.commons.net.ftp.FTPClient.storeFile(String remote,InputStream local) throws IOException

       可以通過使用直接獲取遠程目錄創建文件、然後拿到輸出流將文件寫入,這樣可以手動控制文件的上傳,也可以實現斷點續傳。這是一種辦法,推薦使用這種辦法。

       2、這個方案是通過主線程和子線程的方式來實現,將文件上傳放在子線程裏,主線程負責開啓上傳子線程和監聽子線程文件上傳是否完成,如果遇到不響應的情況,主線程會判斷文件上傳是否完成,如果完成則強制關閉子線程使用的文件流,然後讀取新的文件繼續開啓新的線程來執行上傳。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章