Java 从服务端向客户端文件传输

简介

____最近看Gem5,需要用到Linux系统下的一些回馈,为了简化分析,就想要直接把生成的数据文件下载到本地。搜索了几篇博客,大多是讲将文件从客户端发给云服务器的。我自己学习了一下,并且加以修改,写了一个简单的从服务端向客户端反馈文件的程序。


服务端思路:

服务端通过阻塞式接受请求获得连接,建立线程开始处理此请求。通过文件流的方式传输给客户端,这个过程可以放在对客户端发出的一系列请求之后,各位可以自行添加。


客户端思路:

由于本文是由服务端向客户端发文件,且必定需要收到一个文件,所以只需要在线性执行等待接收文件的过程即可,接收完再关闭连接。相对于服务端,客户端通过写入流,将文件保存到指定目录(若不存在则创建目录)的同名文件。


以下为代码实现

服务端源码

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.net.ServerSocket;
import java.net.Socket;


/**
 * 文件传输server(由服务器发送)
 * 
 * @author Walskor
 * @Date 2020年3月28日
 * @version 1.0
 */
public class Transfer_Server extends ServerSocket{
	private static final int Server_PORT = 8888; //服务器端口
	
	private ServerSocket server;
	
	
	public Transfer_Server() throws Exception{
		super(Server_PORT);
		this.server = this;
	}
	
	public static void main(String[] args) {
		System.out.println("Server starting...");
		
		try {
			Transfer_Server transfer = new Transfer_Server();
			transfer.waiting();
			if(transfer!=null) {
				transfer.close();
			}
		} catch (Exception e) {
			System.out.println("Error: "+ e.getMessage());
		}
	}
	/**
	 * 等待连接
	 * @throws Exception
	 */
	public void waiting() throws Exception{
		while(true) {
			//当阻塞时接受新的连入请求
			Socket client = this.accept();
			//并建立新的线程进行处理
			new Handler(client);
		}
	}
}
/**
 * 线程处理类
 * @author Walskor
 *
 */

class Handler implements Runnable{
	private String FileURL = null;  //文件路径
	
	private Socket socket;
	
	private FileInputStream fileIn;
	private DataOutputStream DataOUT;
	
	public Handler(Socket client) {
		this.socket = client;
		new Thread(this).start();
	}
	
	@Override
	public void run() {
		try {
			setFileURL("D:\\DownLoads\\Chrome\\161840230754060.doc ");
			sendFile(FileURL);  //传输文件
			if(socket!=null) {
				try {
					socket.close();
				} catch (Exception e) {
					socket = null;
					System.out.println("Finally error: "+e.getMessage());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}//end run()
	
	/**
	 * 向客户端传输文件
	 * @throws Exception
	 */
	private void sendFile(String url) throws Exception {
		try {
			File file = new File(url);
			if(file.exists()) {
				fileIn = new FileInputStream(file);
				
				DataOUT = new DataOutputStream(socket.getOutputStream());
			
				//文件名和长度
				DataOUT.writeUTF(file.getName());
				DataOUT.flush();
				DataOUT.writeLong(file.length());
				DataOUT.flush();
			
				//开始传输文件
				System.out.println("=========Start to transfer=========");
				byte[] bytes = new byte[1024];
				int length = 0;
				long progress = 0;
				while((length = fileIn.read(bytes, 0, bytes.length)) != -1) {
					DataOUT.write(bytes, 0, length);
					DataOUT.flush();
					progress += length;
					System.out.println("| "+(100*progress/file.length()) + "% |");
				}
				System.out.println();
				System.out.println("=====File transferred successfully=====");
			}
		} catch (Exception  e) {
			e.printStackTrace(); 
		}finally {                                //关闭数据流
			if(fileIn != null) {
				fileIn.close();
			}
			if(DataOUT != null) {
				DataOUT.close();
			}
		}
	}// end sendFile
	
	
	public void setFileURL(String fileURL) {
		FileURL = fileURL;
	}
}


客户端源码

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.math.RoundingMode;
import java.net.Socket;
import java.text.DecimalFormat;

/**
 * 文件传输Client(由服务器发送)
 * 
 * @author Walskor
 * @Date 2020年3月28日
 * @version 1.0
 */

public class Transfer_Client extends Socket{
	private static final String Server_IP = "localhost";  //服务端IP
	private static final int Server_PORT = 8888;       //服务端端口号
	private Socket server;
	private DataOutputStream outputStream;
	
	/**'
	 * 构造函数
	 * 与服务器建立连接
	 * @throws Exception
	 */
	public Transfer_Client() throws Exception{
		super(Server_IP , Server_PORT);
		this.server = this;
		this.outputStream = new DataOutputStream(
				server.getOutputStream());
		System.out.println("this cilent[port:"+this.getLocalPort()+"] attach to server successfully");
	}
	
	/**
	 * 发送参数
	 * @throws Exception
	 */
	public void send() throws Exception{		
		outputStream.writeUTF("假装这是一条有用的数据流");
		
		//清空数据流
		outputStream.flush();   
	}
	
	
	/**
	 * 接收文件
	 * @throws Exception
	 */
	public void load() throws Exception{
		Load_File load_File = new Load_File(this);
		load_File.get();
		System.out.println("end of load");
	}
	
	public static void main(String[] args) {
		try {
			Transfer_Client TC = new Transfer_Client();
			TC.send();
			TC.load();
			//关闭数据流
			if(TC.outputStream  !=  null) {  
				try {
					TC.outputStream.close();
				} catch (Exception e) {
					TC.outputStream = null;
					e.printStackTrace();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}
}
class Load_File{
	private Socket socket;
	public String fileName;
	public long fileLength;
	private DataInputStream diStream;
	private FileOutputStream foStream;
	
	private static DecimalFormat dFormat = null;
	
	static {
		dFormat = new DecimalFormat("#0.0");
		dFormat.setRoundingMode(RoundingMode.HALF_UP);
		dFormat.setMinimumFractionDigits(1);
		dFormat.setMaximumFractionDigits(1);
	}//设置数字格式,保留一位有效数字
	
	public Load_File(Socket socket) {
		this.socket = socket;
	}
	public void get() {
		try {
			diStream = new DataInputStream(socket.getInputStream());
			
			//文件名和长度
			 fileName = diStream.readUTF();
			 fileLength = diStream.readLong();
			 File directory = new File("D:\\AAAA");
			 if(!directory.exists()) {
				 directory.mkdir();
			 }
			 File file = new File(directory.getAbsolutePath() + File.separatorChar + fileName);
			 foStream = new FileOutputStream(file);
			 
			 //开始接收文件
			 byte[] bytes = new byte[1024];
			 int length = 0;
			 while((length = diStream.read(bytes, 0, bytes.length)) != -1) {
				 foStream.write(bytes, 0, length);
				 foStream.flush();
			 }
			 System.out.println("File received [ File Name: "+ fileName +" ] [ Size: " + getFormatFileSize(fileLength) + " ] ===");	 
		 
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(foStream != null) foStream.close();
				if(diStream != null) diStream.close();
				socket.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
			
		}// end try
		
	}// end get
	
	/**
	 * 格式化文件大小
	 * @param length
	 * @return
	 */
	private String getFormatFileSize(long length) {
		double size = ((double) length) / (1 << 30);
		if(size >= 1) {
			return dFormat.format(size)+"GB";
		}
		size = ((double) length) / (1 << 20);
		if(size >= 1) {
			return dFormat.format(size)+"MB";
		}
		size = ((double) length) / (1 << 10); 
		if(size >= 1) {
			return dFormat.format(size)+"KB";
		}
		return length+"B";
	}
}

运行结果

服务端测试结果:1
服务端测试结果


客户端测试结果:
客户端测试结果

如果需要客户端向服务器的文件传输,推荐:
Java Socket实现文件传输
Java socket 简单实现向云服务器传输文件


  1. 为了方便演示效果,用了很小的文件 ↩︎

发布了3 篇原创文章 · 获赞 8 · 访问量 800

猜你喜欢

转载自blog.csdn.net/weixin_43324750/article/details/105169518