需求
请编写程序,分别模拟使用TCP协议传输数据的客户端和服务器端,完成文件上传。
客户端获取键盘录入的文件路径,将文件上传给服务器端,服务器端获取到数据后,
保存到当前模块目录下,并给出反馈。其中,上传的文件仅允许jpg格式的图片,
保存到服务器端的文件,为防止重名覆盖,可使用32位UUID作为文件名。在实际生产中,32位UUID的获取方式如下:
String uuid = UUID.randomUUID().toString().replaceAll("-", “”);
服务器端有可能接收多个客户端的上传请求,所以服务器端可以使用多线程实现,
为每个客户端开启一条线程完成上传。
程序运行,客户端控制台显示的信息如下:
请输入一个jpg图片文件的路径:
d:\itheima\mn.jpg
服务器端反馈:
上传成功
客户端:
import java.io.*;
import java.net.Socket;
import java.util.Scanner;
// 文件上传的客户端
public class CilentDemo {
public static void main(String[] args) throws IOException {
// 将键盘录入一个文件封装成一个方法
File file = getJpgFile();
// 创建客户端Socket对象,指定访问的地址和端口号
Socket socket = new Socket("127.0.0.1", 11111);
// 创建输入流读取文件数据
BufferedInputStream input = new BufferedInputStream(new FileInputStream(file));
// 根据socket获取输出流,将数据发送给服务器
BufferedOutputStream output = new BufferedOutputStream(socket.getOutputStream());
// 读写操作
int len;
byte[] bys = new byte[1024];
while ((len = input.read(bys)) != -1) {
output.write(bys, 0, len);
output.flush(); // 刷新
}
// 文件数据写完,禁用输出流
socket.shutdownOutput();
// 关闭读取文件的流
input.close();
// 根据socket获取输入流,读取服务端的反馈
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String result = reader.readLine();
System.out.println(result);
// 释放socket资源
socket.close();
}
// 获取jpg图片文件的方法
private static File getJpgFile() {
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个JPG格式图片文件的路径:");
while (true) {
File file = new File(sc.nextLine());
if (!file.exists()) {
System.out.println("该文件路径不存在,请重新输入:");
} else if (file.isDirectory()) {
System.out.println("您输入的是一个文件夹路径,请重新输入:");
} else if (file.getName().endsWith(".jpg") || file.getName().endsWith(".JPG")) {
return file;
} else {
System.out.println("您输入文件格式有误,请重新输入");
}
}
}
}
服务器端:
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
// 文件上传的服务器端
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 创建服务器端对象
ServerSocket serverSocket = new ServerSocket(11111);
System.out.println("服务器启动,绑定端口11111");
while (true) {
// 监听连接,接收客户端的请求,每当有请求就建立一个连接
Socket socket = serverSocket.accept();
// 开启线程
new Thread(new ServerThread(socket)).start();
}
}
}
import java.io.*;
import java.net.Socket;
import java.util.UUID;
public class ServerThread implements Runnable {
private Socket socket;
public ServerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
// 根据socket对象获取输入流,读取客户端发送的数据
BufferedInputStream input = new BufferedInputStream(socket.getInputStream());
// 为防止文件名称重复,采用32位UUID作为文件名
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
// 创建输出流指向当前模块目录,保存文件
BufferedOutputStream output = new BufferedOutputStream(new FileOutputStream("day12_socket\\" + uuid + ".jpg"));
// 读写操作
int len;
byte[] bys = new byte[1024];
while ((len = input.read(bys)) != -1) {
output.write(bys, 0, len);
}
// 读取完文件数据,把socket输入流禁用
socket.shutdownInput();
// 关闭操作当前文件的流
output.close();
// 根据socket对象获取输出流,给客户端反馈
PrintWriter writer = new PrintWriter(socket.getOutputStream(), true);
writer.println("上传成功");
// 释放socket资源
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}