day04-2发送文件
多用户即时通讯系统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("
" + 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("
" + message.getSender() + " 给 " + message.getGetter() +
" 发送文件: " + message.getSrc() + " 到我的电脑的目录:" + message.getDest());
//取出message文件的字节数组,通过文件输出流写出到磁盘
FileOutputStream fileOutputStream =
new FileOutputStream(message.getDest());
fileOutputStream.write(message.getFileBytes());
fileOutputStream.close();
System.out.println("
保存文件成功~");
}
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.服务端
功能实现完毕