00023.10 TCP协议编程:客户端文件上传(存哪、避免重名问题时间戳、多客户端同时上传多线程)

系列文章目录

前言

怎么从客户端上传一个文件到服务端

一、怎么做

(1)服务端

我们先假设只接收一个文件,不考虑多个
在这里插入图片描述
下面思考几个问题

从客户端发送文件到服务器端,服务端要做的事情
(1)接收客户端的连接
(2)接收文件名.后缀名
思考: 存哪里 ①在当前项目中找一个位置存储,例如:upload文件夹
如何解决文件名重名的问题 文件名需要处理,加入时间戳或其他的唯一编码的UUID等值
.后缀名需要保留,因为它代表文件的类型
(3)接收文件内容
(4)反馈结果

下面新建一个保存文件的地方
在这里插入图片描述
思考,要用什么流呢?
a、
这里既要接收文件名.后缀名,又要接收文件内容
这里既有 文本信息“文件名.后缀名”,又有其他类型的数据“文件内容”,只能选择字节流。

b、字节流如何区别,文件名.后缀名 与 文件内容呢?(我怎么知道你5个字节代表的是文件名还是10个字节代表的是后缀名)
想哪种字节输入流,可以处理字符串,和字节类型的数据。
FileInputStream、BufferedInputStream、DataInputStream、ObjectInputStream

这些里面可用的:DataInputStream:readUTF() 和 read(byte[])
ObjectInputStream也可以,但是麻烦,我这里选择DataInputStream

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
因为输出流是独立的,所以也要记得关闭
至此服务端就完成了

(2)客户端

从客户端发送文件到服务器端,客户端要做的事情
(1)从键盘输入文件的路径名,即选择要发送的文件
(2)给服务器先把“文件名.后缀名"
(3)发送文件内容
(4)接收服务器的反馈结果

这里同样因为既要发送“文件名.后缀名",又要发送“文件内容”,选择字节流,选择DataOutputStream

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
效果如下
在这里插入图片描述
在这里插入图片描述

二、多个客户端同时发送文件

跟上篇文章一样,只需要改服务器端
改成多线程即可
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、代码

服务端:

package com.atguigu.test14;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class TestServer {
	public static void main(String[] args) throws IOException {
		//1、开启服务器
		ServerSocket server = new ServerSocket(9999);
		
		//2、接收客户端的连接
		Socket socket = server.accept();
		
		//3、获取输入流
		InputStream in = socket.getInputStream();
		DataInputStream dis = new DataInputStream(in);
		
		//接收文件名.后缀名
		String fileName = dis.readUTF();
		
		//处理文件名
		/*
		 * 希望我要在服务器存储的文件名:   原来的文件名 + 时间戳
		 */
		long timestamp = System.currentTimeMillis();
		//.的下标
		int index = fileName.lastIndexOf(".");
		//后缀名
		String ext = fileName.substring(index);
		// 原来的文件名
		String name = fileName.substring(0, index);
		//新文件名
		String newFileName = "upload/" + name + timestamp + ext;
		
		//创建文件输出流,把接收到的文件内容,写入新文件
		FileOutputStream fos = new FileOutputStream(newFileName);
		
		//接收文件内容
		byte[] data = new byte[1024];
		int len;
		while((len = dis.read(data))!=-1){
			fos.write(data, 0, len);
		}
		
		//还可以给客户端反馈:文件接收完毕
		OutputStream out = socket.getOutputStream();
		PrintStream ps = new PrintStream(out);
		ps.println("文件接收完毕!");
		
		//断开
		fos.close();
		socket.close();
		server.close();
	}
}

客户端:

package com.atguigu.test14;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

/*
 * 从客户端发送文件到服务器端
 * 
 * 
 * 客户端:
 * (1)从键盘输入文件的路径名,即选择要发送的文件
 * (2)给服务器先把“文件名.后缀名"
 * (3)发送文件内容
 * (4)接收服务器的反馈结果
 * 
 * 这里同样因为既要发送“文件名.后缀名",又要发送“文件内容”,选择字节流,选择DataOutputStream
 * 
 */
public class TestClient {
	public static void main(String[] args) throws UnknownHostException, IOException {
		//1、连接服务器
		Socket socket = new Socket("192.168.30.142",9999);
		
		//2、从键盘输入文件的路径名,即选择要发送的文件
		Scanner input = new Scanner(System.in);
		System.out.print("请选择你要发送的文件(例如:D:/尚硅谷_190513班_柴林燕_JavaSE/开学典礼所发资料.rar):");
		String fileName = input.nextLine();
		File file = new File(fileName);
		
		//3、给服务器发送“文件名.后缀名"
		OutputStream out = socket.getOutputStream();
		DataOutputStream dos = new DataOutputStream(out);
		
		//发送“文件名.后缀名"
		dos.writeUTF(file.getName());
		
		//4、发送文件内容
		//先从file文件读取内容
		FileInputStream fis = new FileInputStream(file);
		byte[] data = new byte[1024];
		int len;
		while((len = fis.read(data)) != -1){
			//一边读,一边给服务器发送
			dos.write(data,0,len);
		}
		socket.shutdownOutput();//表示发送完毕了
		
		//5、接收反馈
		InputStream in = socket.getInputStream();
		InputStreamReader isr = new InputStreamReader(in);
		BufferedReader br = new BufferedReader(isr);
		String result = br.readLine();
		System.out.println("结果:" + result);
		
		//6、关闭
		socket.close();
		fis.close();
	}
}

服务器端,多个客户端同时向服务器上传文件
(只需要改服务器端)

package com.atguigu.test15;

import java.io.DataInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

/*
 * 从客户端发送文件到服务器端
 * (1)接收客户端的连接
 * (2)接收文件名.后缀名
 * 思考:
 * 	 存哪里   ①在当前项目中找一个位置存储,例如:upload文件夹
 *  如何解决文件名重名的问题         文件名需要处理,加入时间戳或其他的唯一编码的UUID等值
 *  .后缀名需要保留,因为它代表文件的类型
 * (3)接收文件内容
 * (4)反馈结果
 * 
 * 思考:
 * 		这里既要接收文件名.后缀名,又要接收文件内容。
 * 		这里既有  文本信息“文件名.后缀名”,又有其他类型的数据“文件内容”,只能选择字节流。
 * 
 * 		如何区别,文件名.后缀名   与  文件内容呢
 * 		想哪种字节输入流,可以处理字符串,和字节类型的数据。
 * 
 * 		FileInputStream
 * 		BufferedInputStream
 * 		DataInputStream
 * 		ObjectInputStream
 * 
 * 		这些里面:DataInputStream:readUTF() 和  read(byte[])
 * 				ObjectInputStream也可以,但是麻烦,我这里选择DataInputStream
 * 
 *  加一个条件:同时多个客户端给服务器发送文件,客户端不用修改,服务器端加入多线程
 */
public class TestServer {
	public static void main(String[] args) throws IOException {
		//1、开启服务器
		ServerSocket server = new ServerSocket(9999);
		
		while(true){
			//2、接收客户端的连接
			Socket socket = server.accept();
			
			FileUploadThread ft = new FileUploadThread(socket);
			ft.start();
		
		}
//		server.close();//不关闭服务器
	}
}
class FileUploadThread extends Thread{
	private Socket socket;
	
	public FileUploadThread(Socket socket) {
		super();
		this.socket = socket;
	}

	public void run(){
		try {
			//3、获取输入流
			InputStream in = socket.getInputStream();
			DataInputStream dis = new DataInputStream(in);
			
			//接收文件名.后缀名
			String fileName = dis.readUTF();
			
			//处理文件名
			/*
			 * 希望我要在服务器存储的文件名:   原来的文件名 + 时间戳
			 */
			long timestamp = System.currentTimeMillis();
			//.的下标
			int index = fileName.lastIndexOf(".");
			//后缀名
			String ext = fileName.substring(index);
			// 原来的文件名
			String name = fileName.substring(0, index);
			//新文件名
			String newFileName = "upload/" + name + timestamp + ext;
			
			//创建文件输出流,把接收到的文件内容,写入新文件
			FileOutputStream fos = new FileOutputStream(newFileName);
			
			//接收文件内容
			byte[] data = new byte[1024];
			int len;
			while((len = dis.read(data))!=-1){
				fos.write(data, 0, len);
			}
			
			//还可以给客户端反馈:文件接收完毕
			OutputStream out = socket.getOutputStream();
			PrintStream ps = new PrintStream(out);
			ps.println("文件接收完毕!");
			
			//断开
			fos.close();
			socket.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

总结

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值