文件的上传需要保证数据的安全性、完成性以及连接性,所以使用 TCP 协议来实现,这里就以上传一张图片文件为例,分别使用单线程和多线程来实现,单线程就是一个服务器接收一个客户端发来的图片,多线程就是一个服务器同时接收多个客户端发来的图片。
一、单线程实现
(1) 客户端实现:
- Socket 套接字连接服务器
- 通过 Socket 获取字节输出流,进行写图片
- 使用自己的流对象读取图片流资源
- 读取图片,使用字节输出流将图片写到服务器,采用字节数组进行缓冲
- 通过 Socket 套接字获取字节输入流
- 获取服务器端的反馈回来的信息
- 关闭流资源
/**
* 客户端实现
* 1、Socket 套接字连接服务器
* 2、通过 Socket 获取字节输出流,进行写图片
* 3、使用字节流对象读取图片流资源
* 4、读取图片,使用字节输出流将图片写到服务器,采用字节数组进行缓冲
* 5、通过 Socket 套接字获取字节输入流
* 6、获取服务器端的反馈回来的信息
* 7、关闭流资源
*/
public static void main(String[] args) throws IOException {
//1、Socket 套接字连接服务器
Socket socket = new Socket(InetAddress.getLocalHost().getHostAddress(),8888);
//2、通过 Socket 获取字节输出流,进行写图片
OutputStream OS = socket.getOutputStream();
//3、使用字节流对象读取图片流资源
FileInputStream FIS = new FileInputStream("F:\\De-lovely\\LR_Mountain_Hand.jpg");
//4、读取图片,使用字节输出流将图片写到服务器,采用字节数组进行缓冲\
int length;
byte[] bytes = new byte[1024];
while ((length = FIS.read(bytes)) != -1)
{
//5、通过 Socket 套接字获取字节输入流
OS.write(bytes,0,length);
}
//给服务器写终止序列
socket.shutdownOutput();
//6、获取服务器端的反馈回来的信息
InputStream IS = socket.getInputStream();
length = IS.read(bytes);
System.out.println(new String(bytes,0,length));
//7、关闭流资源
FIS.close();
socket.close();
}
(2) 服务器实现
- 创建 ServerSocket 套接字对象,监听端口
- accept() 方法获取客户端的连接对象
- 客户端连接对象获取字节输入流,读取客户端发送的图片
- 创建 File 对象,绑定上传文件夹
- 创建字节输出流
- 字节流得到图片,将图片写进写到文件夹中
- 发送消息给客户端
- 关闭流资源
/**
* 服务器实现
* 1、创建 ServerSocket 套接字对象,监听端口
* 2、accept() 方法获取客户端的连接对象
* 3、客户端连接对象获取字节输入流,读取客户端发送的图片
* 4、创建 File 对象,绑定上传文件夹
* 5、创建字节输出流
* 6、字节流得到图片,将图片写进写到文件夹中
* 7、发送消息给客户端
* 8、关闭流资源
*/
public static void main(String[] args) throws IOException {
//1、创建 ServerSocket 套接字对象,监听端口
ServerSocket ser = new ServerSocket(8888);
//2、accept() 方法获取客户端的连接对象
Socket soc = ser.accept();
//3、客户端连接对象获取字节输入流,读取客户端发送的图片
InputStream IS = soc.getInputStream();
//4、创建 File 对象,绑定上传文件夹
String FileName = "Love" + System.currentTimeMillis() + new Random().nextInt(999999)+ ".jpg";
BufferedOutputStream BOS = new BufferedOutputStream(new FileOutputStream("C:\\Users\\OneStar\\Desktop\\"+FileName));
//5、创建字节输出流
byte[] bytes = new byte[1024];
int length;
//6、字节流得到图片,将图片写进写到文件夹中
while ((length = IS.read(bytes)) != -1)
{
BOS.write(bytes,0,length);
}
//7、发送消息给客户端
OutputStream OS = soc.getOutputStream();
OS.write("图片上传成功!".getBytes());
OS.flush();
//8、关闭流资源
soc.close();
BOS.close();
OS.close();
}
二、多线程实现
多线程实现文件上传只要修改服务器代码即可,修改如下
//在main中创建线程
public static void main(String[] args) throws IOException {
//1、创建 ServerSocket 套接字对象,监听端口
ServerSocket SS = new ServerSocket(8888);
while (true)
{
//2、获取到一个客户端就开启一个新线程
Socket soc = SS.accept();
Upload load = new Upload(soc);
Thread T1 = new Thread(load);
T1.start();
}
}
//在Upload类中实现Runable接口,重写run方法
public class Upload implements Runnable {
private Socket soc;
public Upload(Socket soc){
this.soc = soc;
}
public void run() {
try {
//3、客户端连接对象获取字节输入流,读取客户端发送的图片
InputStream IS = soc.getInputStream();
//4、创建 File 对象,绑定上传文件夹
String FileName = "Love" + System.currentTimeMillis() + new Random().nextInt(999999) + ".jpg";
BufferedOutputStream BOS = new BufferedOutputStream(new FileOutputStream("C:\\Users\\OneStar\\Desktop\\" + FileName));
//5、创建字节输出流
byte[] bytes = new byte[1024];
int length;
//6、字节流得到图片,将图片写进写到文件夹中
while ((length = IS.read(bytes)) != -1) {
BOS.write(bytes, 0, length);
}
//7、发送消息给客户端
OutputStream OS = soc.getOutputStream();
OS.write("图片上传成功!".getBytes());
OS.flush();
//8、关闭流资源
BOS.close();
OS.close();
}
catch (Exception e){
}
}
}