综合案例:文件上传案例
-
TCP文件上传案例 -
客户端读取本地文件,把文件上传到服务器,服务器把上传的文件保存到硬盘上 -
1.客户端使用本地的字节输出流(FileInputStream对象),构造方法绑定要读取上传的文件 -
2.创建客户端Socket对象,构造方法绑定客户端的IP地址和端口号,客户端使用网络字节输出流(getOutputStream)的方法write把读取到的文件上传到服务器 -
(注意:客户端的本地字节输入流读取文件时不会读取到结束标志-1,所以客户端的网络字节输出流也不会给服务器上传结束标志-1) -
3.服务器网络字节输入流(getInputStream)读取(read)客户端上传的文件 -
(注意:由于客户端的网络字节输出流不会上传结束标志-1,所以服务器的网络字节输入流的read方法不会读取到结束标志,所以会进入阻塞状态,一直死循环等待结束标志,所以服务器的回写代码不会被执行,客户端的接收回写的网络字节输入流也不起作用,进入阻塞状态) -
4.服务器使用本地的字节输出流(FileOutputStream),把读取到的文件,保存到服务器的硬盘上 -
5.服务器使用网络字节输出流,给客户端回写一个"上传成功" -
6.客户端使用网络字节输入流读取服务器回写的数据 -
7.释放资源 - ? ?
-
客户端和服务器和本地硬盘进行读写需要使用自己创建的本地字节流对象,客户端和服务器之间进行数据的传输需要网络字节流对象 - ? ?
-
文件上传的原理:文件的赋值 -
明确:数据源和数据复制的目的地
客户端实现:
public static void main(String[] args) throws IOException {
? ?//1.客户端使用本地的字节输出流(FileInputStream对象),构造方法绑定要读取上传的文件
? ?FileInputStream fis = new FileInputStream("D:\\1.png");
? ?//2.创建客户端Socket对象,构造方法绑定客户端的IP地址和端口号
? ?Socket socket = new Socket("127.0.0.1", 8888);
? ?//客户端获取网络字节输出流上传数据至服务器
? ?OutputStream outputStream = socket.getOutputStream();
? ?int len = 0;
? ?byte[] bytes = new byte[1024];
? ?//注意:客户端的本地字节输入流读取文件时不会读取到结束标志-1,所以客户端的网络字节输出流也不会给服务器上传结束标志-1
? ?while ((len = fis.read(bytes)) != -1) {
? ? ? ?//客户端使用网络字节输出流(getOutputStream)的方法write把读取到的文件上传到服务器
? ? ? ?outputStream.write(bytes, 0, len);
? }
? ?//终止网络字节输出流,解决阻塞问题
? ?socket.shutdownOutput();
? ?//客户端使用网络字节输入流读取服务器回写的数据
? ?InputStream inputStream = socket.getInputStream();
? ?while ((len = inputStream.read(bytes)) != -1) {
? ? ? ?System.out.println(new String(bytes, 0, len));
? }
? ?//释放资源
? ?fis.close();
? ?socket.close();
}
服务器实现:
public static void main(String[] args) throws IOException {
? ?ServerSocket server = new ServerSocket(8888);
? ?//让服务器一直处于监听状态,有一个客户端上传文件,就保存一个文件
? ?while (true) {
? ? ? ?//当存在多个客户端时,效率会很低,可以使用多线程提高效率
? ? ? ?new Thread(new Runnable() {
? ? ? ? ? ?@Override
? ? ? ? ? ?public void run() {
? ? ? ? ? ? ? ?//run方法接口没有声明抛出异常,所以重写run方法也不能声明抛出
? ? ? ? ? ? ? ?try {
? ? ? ? ? ? ? ? ? ?//获取到请求的客户端对象
? ? ? ? ? ? ? ? ? ?Socket accept = server.accept();
? ? ? ? ? ? ? ? ? ?//获取网络字节输入流用来读取客户端上传的文件
? ? ? ? ? ? ? ? ? ?InputStream is = accept.getInputStream();
? ? ? ? ? ? ? ? ? ?File file = new File("D:\\pngcopy");
? ? ? ? ? ? ? ? ? ?if (!file.exists()) {
? ? ? ? ? ? ? ? ? ? ? ?file.mkdirs();
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ?//自定义一个命名规则,防止重名的文件被覆盖掉
? ? ? ? ? ? ? ? ? ?String Filename = "itcast" + System.currentTimeMillis() + new ???????????????? Random().nextInt(9999) + ".png";
? ? ? ? ? ? ? ? ? ?//创建一个本地的字节输出流,用于向服务器本地磁盘上传文件
? ? ? ? ? ? ? ? ? ?FileOutputStream fos = new FileOutputStream(file + "\\" + ????????????????????Filename);
? ? ? ? ? ? ? ? ? ?int len = 0;
? ? ? ? ? ? ? ? ? ?byte[] bytes = new byte[1024];
? ? ? ? ? ? ? ? ? ?//注意is的read方法读取客户端上传的文件,永远读取不到结束标志-1,所以read方法会进入阻塞状态,一直死循环等待结束标志
? ? ? ? ? ? ? ? ? ?while ((len = is.read(bytes)) != -1) {
? ? ? ? ? ? ? ? ? ? ? ?fos.write(bytes, 0, len);
? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ?OutputStream os = accept.getOutputStream();
? ? ? ? ? ? ? ? ? ?os.write("上传成功".getBytes());
? ? ? ? ? ? ? ? ? ?fos.close();
? ? ? ? ? ? ? ? ? ?accept.close();
? ? ? ? ? ? ? } catch (IOException e) {
? ? ? ? ? ? ? ? ? ?System.out.println(e);
? ? ? ? ? ? ? }
? ? ? ? ? }
? ? ? }).start();
? ? ? ?//服务器不用关闭,所以close方法可以不调用
? ? ? ?//server.close();
? }
}
|