多用戶即時通訊系統04 4.編碼實現03 4.6功能實現-發送文件功能實現 4.6.1思路分析 客戶端(發送者): 先把文件a.jpg讀取到客戶端的位元組數組 把文件對應的位元組數組封裝到message對象[包含文件內容,發送者,接收者] 將message對象發送到服務端 服務端: 接收到message ...
多用戶即時通訊系統04
4.編碼實現03
4.6功能實現-發送文件功能實現
4.6.1思路分析
客戶端(發送者):
- 先把文件a.jpg讀取到客戶端的位元組數組
- 把文件對應的位元組數組封裝到message對象[包含文件內容,發送者,接收者]
- 將message對象發送到服務端
服務端:
- 接收到message對象
- 拆解message對象的getteruid,獲取接收者用戶的通信線程,得到socket
- 把message轉發給指定用戶
客戶端(接收者):
- 在接收到包含有文件的message消息後,讀取對應的文件位元組數組,將該數組刷出到磁碟
4.6.2代碼實現
1. 客戶端:
1.修改MessageType介面
在該介面中拓展消息類型
String MESSAGE_FILE_MES = "8";//表示發送文件消息
2.修改Message類
擴展 和文件相關的成員和方法
//進行擴展 和文件相關的成員
private byte[] fileBytes;
private int fileLen = 0;
private String dest ;//將文件傳輸到哪裡
private String src;//源文件路徑
public byte[] getFileBytes() {
return fileBytes;
}
public void setFileBytes(byte[] fileBytes) {
this.fileBytes = fileBytes;
}
public int getFileLen() {
return fileLen;
}
public void setFileLen(int fileLen) {
this.fileLen = fileLen;
}
public String getDest() {
return dest;
}
public void setDest(String dest) {
this.dest = dest;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
3.創建FileClientService
該類完成文件傳輸服務
package qqclient.service;
import qqcommon.Message;
import qqcommon.MessageType;
import java.io.*;
/**
* @author 李
* @version 1.0
* 該類完成 文件傳輸服務
*/
public class FileClientService {
/**
* @param src 源文件
* @param dest 把該文件傳輸到對方的哪個目錄
* @param senderId 發送用戶的id
* @param getterId 接收用戶的id
*/
public void sendFileToOne(String src, String dest, String senderId, String getterId) {
//讀取src文件--封裝-->message對象
Message message = new Message();
message.setMesType(MessageType.MESSAGE_FILE_MES);//設置為文件類型
message.setSender(senderId);
message.setGetter(getterId);
message.setSrc(src);
message.setDest(dest);
//需要將文件讀取到程式中
FileInputStream fileInputStream = null;
byte[] fileBytes = new byte[(int) new File(src).length()];//創建一個和文件大小對應的位元組數組
try {
fileInputStream = new FileInputStream(src);
fileInputStream.read(fileBytes);//將src的文件讀入到程式的位元組數組
//將文件對應的位元組數組設置成message對象
message.setFileBytes(fileBytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (fileInputStream != null) {
try {
//關閉流
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("\n" + senderId + " 給 " + getterId + " 發送文件:" + src +
" 到對方的電腦目錄: " + dest);
//發送
try {
//從管理線程的集合中,拿到發送者id的線程,
// 在該線程對應的屬性socket中得到輸出流,將輸出流轉為對象輸出流
ObjectOutputStream oos =
new ObjectOutputStream(ManageClientConnectServerThread.getClientConnectServerThread(senderId).getSocket().getOutputStream());
oos.writeObject(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4.修改ClientConnectServerThread類
在在該類中增加接收message消息的類型,併進行相應的操作
else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)) {
//接收到的是文件類型的消息
//把伺服器轉發的message對象
System.out.println("\n" + message.getSender() + " 給 " + message.getGetter() +
" 發送文件: " + message.getSrc() + " 到我的電腦的目錄:" + message.getDest());
//取出message文件的位元組數組,通過文件輸出流寫出到磁碟
FileOutputStream fileOutputStream =
new FileOutputStream(message.getDest());
fileOutputStream.write(message.getFileBytes());
fileOutputStream.close();
System.out.println("\n保存文件成功~");
}
5.修改QQView
1.在該類中創建FileClientService對象
private FileClientService fileClientService = new FileClientService();//該對象用於文件傳輸
在該類中通過鍵盤,將用戶輸入傳送到sendFileToOne方法中
case "4":
System.out.println("請輸入你希望發送文件的用戶(線上):");
getterId = Utility.readString(50);
System.out.println("請輸入要發送文件的路徑:(形式如:d:\\xx.jpg)");
String src = Utility.readString(100);
System.out.println("請輸入把文件發送到對方電腦下的路徑:(形式如:d:\\yy.jpg)");
String dest = Utility.readString(100);
fileClientService.sendFileToOne(src,dest,userId,getterId);
break;
2.服務端
1.修改MessageType介面
在該介面中拓展消息類型
String MESSAGE_FILE_MES = "8";//表示發送文件消息
2.修改Message類
擴展 和文件相關的成員和方法
//進行擴展 和文件相關的成員
private byte[] fileBytes;
private int fileLen = 0;
private String dest ;//將文件傳輸到哪裡
private String src;//源文件路徑
public byte[] getFileBytes() {
return fileBytes;
}
public void setFileBytes(byte[] fileBytes) {
this.fileBytes = fileBytes;
}
public int getFileLen() {
return fileLen;
}
public void setFileLen(int fileLen) {
this.fileLen = fileLen;
}
public String getDest() {
return dest;
}
public void setDest(String dest) {
this.dest = dest;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
3.修改ServerConnectClientThread類
在該類的run方法中增加服務端接收文件並轉發的業務
else if (message.getMesType().equals(MessageType.MESSAGE_FILE_MES)) {
//業務五:客戶請求給某用戶發送文件
//根據接收的message對象的getter id 獲取到對應的線程,將message對象進行轉發
//拿到線程
ServerConnectClientThread serverConnectClientThread =
ManageClientThreads.getServerConnectClientThread(message.getGetter());
//獲取socket,將socket輸出流轉為對象流
ObjectOutputStream oos =
new ObjectOutputStream(serverConnectClientThread.getSocket().getOutputStream());
//轉發
oos.writeObject(message);
}
運行:
1.運行服務端
2.運行客戶端,登錄兩個用戶(100,200)
3.用戶100 嘗試給用戶200 發送文件
用戶100:
用戶200:
用戶200的磁碟下成功接收到文件:
4.服務端
功能實現完畢