java聊天室項目
分片上傳
將大文件切分為多個小的數據塊(通常大小為1MB~10MB),然后將這些小數據塊分別上傳至服務器,最后由服務器將這些小塊組合成完整的文件。這種方式可以避免由于網絡中斷或超時而導致上傳失敗,并且能夠更好地控制上傳進度。
- 客戶端將文件切成固定大小的塊(例如每個塊的大小為1MB),并為每個塊生成唯一的標識符。
- 客戶端逐個上傳每個塊到服務器。上傳時,客戶端將塊的標識符和塊數據一起發送給服務器。
- 服務器接收到每個塊后,會將塊數據存儲到臨時文件中,并在服務器端記錄每個塊的標識符和位置。
- 當所有塊都上傳完成后,客戶端向服務器發送一個“合并請求”,請求服務器將所有塊合并成一個完整的文件。
- 服務器接收到“合并請求”后,根據之前記錄的塊標識符和位置信息,將所有塊合并成一個完整的文件。
- 服務器將合并后的文件存儲到指定的位置,并返回上傳成功的響應給客戶端。
- 客戶端收到上傳成功的響應后,通知用戶上傳已完成。
?
?
private static void sendFile(File file, String filename, File selectedFile) throws IOException {LocalDateTime currentDateTime = LocalDateTime.now();DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");String formattedDateTime = currentDateTime.format(formatter); // 格式化當前日期和時間int length = 1024 * 1024 * 5;byte[] bytes = new byte[length];int number = (int) Math.ceil((double) selectedFile.length() / length);FileInputStream fileInputStream = new FileInputStream(selectedFile.getPath());message tomessage = new message(messagetype, user, markTool.filemessage, filename, formattedDateTime, chatgroup, otheruser);connection.oos.writeObject(tomessage);for (int i = 0; i < number; i++) {byte[] buffer = new byte[length];int bytesRead = fileInputStream.read(buffer);message filemessage = new message(buffer, true);connection.oos1.writeObject(filemessage);}byte[] buffer = new byte[length];int bytesRead = fileInputStream.read(buffer);message filemessage = new message(buffer, false);connection.oos1.writeObject(filemessage);System.out.println("文件發送完成,共發送了 " + number + " 個文件塊。");}
文本,文件操作
服務端包括監聽線程和處理收發信線程:
- 創建監聽線程,監聽客戶端的連接。將每個連接的客戶端加入維護的列表,并為每個連接的客戶端開啟一個處理收發信的線程。
- 在每個客戶端的收發信線程中,接收每個客戶端發回的消息,并對其進行轉發到相應接收的客戶端上,以此實現多人聊天室。
- 添加處理傳輸文件的判斷,通過在傳輸的字節數組中添加標志位來區分傳輸的是文本消息,還是文件。
客戶端包括發送消息線程和接收消息線程:
- 發送消息線程,用來處理用戶的輸入信息,判斷輸入的是文本信息還是文件,并修改傳輸的字節數組標志位進行區分。最后將信息傳輸給服務器。
- 接收消息線程,用來處理服務器發回的信息,根據標志位判斷輸入的是文本信息還是文件,并做相應處理。如果是文本信息,則顯示在控制臺,如果是文件,則保存在指定目錄下。
?
?
發送文件(文件選擇器)
//發送圖片點擊事件FileChooser fileChooser = new FileChooser();fileChooser.setTitle("選擇文件");// 添加文件過濾器,僅允許選擇圖片文件fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("圖片文件", "*.png", "*.jpg", "*.gif"));// 顯示文件選擇對話框并獲取用戶選擇的文件Window stage = null;File selectedFile = fileChooser.showOpenDialog(stage);// 如果用戶選擇了文件,則將文件加載到ImageView中顯示
將傳輸的字節數組寫入文件
private static void sendFile(message getmessage,String path) throws IOException, ClassNotFoundException {System.out.println(path);File file = new File(path);FileOutputStream fos = new FileOutputStream(file);while (true) {message message = (message) connection.ois1.readObject();System.out.println(message.Filebytes);System.out.println(message.flag);if (!message.flag) {fos.write(message.Filebytes);fos.flush();break;}fos.write(message.Filebytes);fos.flush();}fos.close();}