1. 程式人生 > >java實現客戶端向伺服器傳送檔案的操作

java實現客戶端向伺服器傳送檔案的操作

伺服器原始碼:

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;


/**
 * 
 * 檔名:ServerReceive.java
 * 實現功能:作為伺服器接收客戶端傳送的檔案
 * 
 * 具體實現過程:
 * 1、建立SocketServer,等待客戶端的連線
 * 2、當有客戶端連線的時候,按照雙方的約定,這時要讀取一行資料
 * 		其中儲存客戶端要傳送的檔名和檔案大小資訊
 * 3、根據檔名在本地建立檔案,並建立好流通訊
 * 4、迴圈接收資料包,將資料包寫入檔案
 * 5、當接收資料的長度等於提前檔案發過來的檔案長度,即表示檔案接收完畢,關閉檔案
 * 6、檔案接收工作結束
 * 
 * 
 * 【注:此程式碼僅為演示客戶端與伺服器傳送檔案使用,
 * 		每一個數據包之前沒有檔案協議命令
 *  	具體的協議傳輸和檔案傳出的使用階段可根據自己程式自行放置】
 * 
 * 
 * 作者:小菜鳥
 * 建立時間:2014-08-19
 * 
 * */




public class ServerReceive {

	public static void main(String[] args) {
		
		/**與伺服器建立連線的通訊控制代碼*/
		ServerSocket ss = null;
		Socket s = null;
		
		/**定義用於在接收後在本地建立的檔案物件和檔案輸出流物件*/
		File file = null;
		FileOutputStream fos = null;
		
		/**定義輸入流,使用socket的inputStream對資料包進行輸入*/
		InputStream is = null;
		
		/**定義byte陣列來作為資料包的儲存資料包*/
		byte[] buffer = new byte[4096 * 5];
		
		/**用來接收檔案傳送請求的字串*/
		String comm = null;
		
		
		/**建立socekt通訊,等待伺服器進行連線*/
		try {
			ss = new ServerSocket(4004);
			s = ss.accept();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
		/**讀取一行客戶端傳送過來的約定資訊*/
		try {
			InputStreamReader isr = new InputStreamReader(s.getInputStream());
			BufferedReader br = new BufferedReader(isr);
			comm = br.readLine();
		} catch (IOException e) {
			System.out.println("伺服器與客戶端斷開連線");
		}
		
		/**開始解析客戶端傳送過來的請求命令*/
		int index = comm.indexOf("/#");
		
		/**判斷協議是否為傳送檔案的協議*/
		String xieyi = comm.substring(0, index);
		if(!xieyi.equals("111")){
			System.out.println("伺服器收到的協議碼不正確");
			return;
		}
		
		/**解析出檔案的名字和大小*/
		comm = comm.substring(index + 2);
		index = comm.indexOf("/#");
		String filename = comm.substring(0, index).trim();
		String filesize = comm.substring(index + 2).trim();
		
		
		/**建立空檔案,用來進行接收檔案*/
		file = new File(filename);
		if(!file.exists()){
			try {
				file.createNewFile();
			} catch (IOException e) {
				System.out.println("伺服器端建立檔案失敗");
			}
		}else{
			/**在此也可以詢問是否覆蓋*/
			System.out.println("本路徑已存在相同檔案,進行覆蓋");
		}
		
		/**【以上就是客戶端程式碼中寫到的伺服器的準備部分】*/
		
		
		/**
		 * 伺服器接收檔案的關鍵程式碼*/
		try {
			/**將檔案包裝到檔案輸出流物件中*/
			fos = new FileOutputStream(file);
			long file_size = Long.parseLong(filesize);
			is = s.getInputStream();
			/**size為每次接收資料包的長度*/
			int size = 0;
			/**count用來記錄已接收到檔案的長度*/
			long count = 0;
			
			/**使用while迴圈接收資料包*/
			while(count < file_size){
				/**從輸入流中讀取一個數據包*/
				size = is.read(buffer);
				
				/**將剛剛讀取的資料包寫到本地檔案中去*/
				fos.write(buffer, 0, size);
				fos.flush();
				
				/**將已接收到檔案的長度+size*/
				count += size;
				System.out.println("伺服器端接收到資料包,大小為" + size);
			}
			
		} catch (FileNotFoundException e) {
			System.out.println("伺服器寫檔案失敗");
		} catch (IOException e) {
			System.out.println("伺服器:客戶端斷開連線");
		}finally{
			/**
			 * 將開啟的檔案關閉
			 * 如有需要,也可以在此關閉socket連線
			 * */
			try {
				if(fos != null)
					fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}//catch (IOException e)
		}//finally

	}//public static void main(String[] args)
}//public class ServerReceive

客戶端原始碼:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;


/**
 * 
 * 檔名:ClientSend.java
 * 實現功能:作為客戶端向伺服器傳送一個檔案
 * 
 * 具體實現過程:
 * 1、建立與伺服器端的連線,IP:127.0.0.1, port:4004
 * 2、將檔案的名字和大小通過自定義的檔案傳輸協議,傳送到伺服器
 * 3、迴圈讀取本地檔案,將檔案打包傳送到資料輸出流中
 * 4、關閉檔案,結束傳輸
 * 
 * 【注:此程式碼僅為演示客戶端與伺服器傳送檔案使用,
 * 		每一個數據包之前沒有檔案協議命令
 *  	具體的協議傳輸和檔案傳出的使用階段可根據自己程式自行放置】
 * 
 * 
 * 作者:小菜鳥
 * 建立時間:2014-08-19
 * 
 * */

public class ClientSend {

	public static void main(String[] args) {
		
		/**與伺服器建立連線的通訊控制代碼*/
		Socket s = null;
		
		/**定義檔案物件,即為要傳送的檔案
		 * 如果使用絕對路徑,不要忘記使用'/'和'\'的區別
		 * 具體區別,請讀者自行查詢
		 * */
		File sendfile = new File("API.CHM");
		/**定義檔案輸入流,用來開啟、讀取即將要傳送的檔案*/
		FileInputStream fis = null;
		/**定義byte陣列來作為資料包的儲存資料包*/
		byte[] buffer = new byte[4096 * 5];
		
		/**定義輸出流,使用socket的outputStream對資料包進行輸出*/
		OutputStream os = null;
		
		
		/**檢查要傳送的檔案是否存在*/
		if(!sendfile.exists()){
			System.out.println("客戶端:要傳送的檔案不存在");
			return;
		}
		
		
		/**與伺服器建立連線*/
		try {
			s = new Socket("127.0.0.1", 4004);
		}catch (IOException e) {
			System.out.println("未連線到伺服器");
		}
		
		/**用檔案物件初始化fis物件
		 * 以便於可以提取出檔案的大小
		 * */
		try {
			fis = new FileInputStream(sendfile);
		} catch (FileNotFoundException e1) {
			e1.printStackTrace();
		}

		
		/**首先先向伺服器傳送關於檔案的資訊,以便於伺服器進行接收的相關準備工作
		 * 具體的準備工作,請檢視伺服器程式碼。
		 * 
		 * 傳送的內容包括:傳送檔案協議碼(此處為111)/#檔名(帶字尾名)/#檔案大小
		 * */
		try {
			PrintStream ps = new PrintStream(s.getOutputStream());
			ps.println("111/#" + sendfile.getName() + "/#" + fis.available());
			ps.flush();
		} catch (IOException e) {
			System.out.println("伺服器連線中斷");
		}
		
		
		/**
		 * 此處睡眠2s,等待伺服器把相關的工作準備好
		 * 也是為了保證網路的延遲
		 * 讀者可自行選擇新增此程式碼
		 * */
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		
		
		
		/**之前的準備工作結束之後
		 * 下面就是檔案傳輸的關鍵程式碼
		 * */
		try {
			
			/**獲取socket的OutputStream,以便向其中寫入資料包*/
			os = s.getOutputStream();
			
			/** size 用來記錄每次讀取檔案的大小*/
			int size = 0;
			
			/**使用while迴圈讀取檔案,直到檔案讀取結束*/
			while((size = fis.read(buffer)) != -1){
				System.out.println("客戶端傳送資料包,大小為" + size);
				/**向輸出流中寫入剛剛讀到的資料包*/
				os.write(buffer, 0, size);
				/**重新整理一下*/
				os.flush();
			}
		} catch (FileNotFoundException e) {
			System.out.println("客戶端讀取檔案出錯");
		} catch (IOException e) {
			System.out.println("客戶端輸出檔案出錯");
		}finally{
			
			/**
			 * 將開啟的檔案關閉
			 * 如有需要,也可以在此關閉socket連線
			 * */
			try {
				if(fis != null)
					fis.close();
			} catch (IOException e) {
				System.out.println("客戶端檔案關閉出錯");
			}//catch (IOException e)
		}//finally
		
	}//public static void main(String[] args)
}//public class ClientSend