1、多线程文件的上传,数据流向 

1)、客户端Socket:

      ①out File对象 

       ②out 文件内容

        ③in 服务端反馈信息 


2)、服务端的处理 

       ①每接收一个Socket,创建一个线程去处理这个Socket 

        ②in File对象:判断文件的类型、选择不同的传输方式、创建File对象关联文件

        ③in 文件内容:填充File对象关联文件内容 

       ④填充完File文件,给客户端反馈

  

   2、代码:                 

  1)客户端:字符流       

 

import java.net.*;
import java.io.*;
/**
 * @author Administrator @zsw 2012-7-18 上午09:21:04
 * 
 * 需求:从客户端上传文本文件到服务端
 * 
 * 客户端上传:
 * ①定义Socket、文件输入流、Socket输出流、Socket输入流
 * ②从文件输入读取文件,
 * 添加:首先上传文件File对象和文件类型int filetype
 * ③将读到的数据写入Socket输出流中
 * ④关闭资源
 */
public class TextUploadClient2 {

	
	public static void main(String[] args) throws Exception{
		File file=new File("D:\\1.txt");
		
		
		//①:定义资源
		Socket s=new Socket("127.0.0.1",10007);
		BufferedReader bufr=new BufferedReader(new FileReader(file));
		//字符流转换成字节流
		BufferedWriter bufout=new BufferedWriter(
				new OutputStreamWriter(s.getOutputStream()));
//		PrintWriter out=new PrintWriter(s.getOutputStream(),true);
		BufferedReader bufin=new BufferedReader(
				new InputStreamReader(s.getInputStream()));
		
		//将文件对象传到服务器
		ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
		oos.writeObject(file);
		
	
		//②上传数据
		String line=null;
		while((line=bufr.readLine())!=null){
			 
//			System.out.println(line);
			bufout.write(line);
			bufout.newLine();
			bufout.flush();
		}
		
		//③告诉服务器,客户端已经传完了。并接收服务端的反馈信息
		 s.shutdownOutput();//关闭客户端的输出流,相当于在流中写-1
		 
		 String line2=null;
		 while((line2=bufin.readLine())!=null){
			 if("success".equals(line2)){	
				 System.out.println("上传文件成功!");
				 break;
			 }
		 }
		
		//④关闭资源
		 bufr.close();
		 s.close();


	}

}



                                     

2)客户端:字符流


import java.io.*;
import java.net.*; 
/**
 * @author Administrator @zsw 2012-7-18 下午06:45:41
 *客户端:
 *①服务端点:Socket、流
 *②读取客户端的图片数据
 *③通过Socket输出流将数据发给服务端
 *④读取服务端反馈信息
 *⑤关闭资源
 */
public class UploadPicClient2 {
	public static void main(String[] args) throws Exception{
		File file=new File("D:\\1.mp3");
		//①服务端点:
		Socket s=new Socket("127.0.0.1",10007);
    	FileInputStream fis=new FileInputStream(file);
		OutputStream out=s.getOutputStream();
		InputStream in=s.getInputStream();
		
		//将文件对象传到服务器
		ObjectOutputStream oos=new ObjectOutputStream(s.getOutputStream());
		oos.writeObject(file);
		
		//②读取图片
		byte[]buf=new byte[1024*2];
		int len=0;
		while((len=fis.read(buf))!=-1){
			//③发送数据到服务端
			out.write(buf, 0, len);	
		}
		//给服务端发送结束标记
		s.shutdownOutput();
		
		//④读取服务端反馈信息
	    len=0;
		while((len=in.read(buf))!=-1){
			String str=new String(buf,0,len);
			System.out.println("服务端反馈:"+str);
		}
		
		//⑤关闭资源
		fis.close();
		s.close();
	}

}



3)服务端:使用多线程

import java.io.*;
import java.net.*;

/**
 * 总结:多线程文件的上传,数据流向
 * 1、客户端Socket:①out File对象 ②out 文件内容 ③in 服务端反馈信息
 *           
 * 3、服务端的处理
 *  ①每接收一个Socket,创建一个线程去处理这个Socket
 *  ②in File对象:判断文件的类型、选择不同的传输方式、创建File对象关联文件
 *  ③in 文件内容:填充File对象关联文件内容
 *  ④填充完File文件,给客户端反馈
 *  
 *  
 * @author Administrator @zsw 2012-7-18 下午07:03:47
 * 此类在UploadPicServer.java上面做改进,使用了多线程.
 * 
 *1单线程服务端:有局限,当A客户连接上来后,<br>
 *被服务器接收后, 服务端执行具体流程中,这时,B客户端连接,只有等待。
 *因为服务端还没有处理完A客户端的请求,
 *还没有循环回来执行下次 accept方法,所以暂时获取不到B客户端对象
 * 
 *2解决思路:那么为了可以让多个客户端同时并发的访问服务器, 
 *服务端最好就是将每一个客户端封装到一个单独的线程中。
 * 
 * 
 * 
 */
/*
 * 如何定义线程呢: 明确每一个客户端要在服务端执行的代码,将该代码放入run方法中
 */
//3、线程类
class UploadThread implements Runnable {
	// 客户端、文件、文件类型(简单点0表示文本、1表示字节流)
	private Socket s;
	UploadThread(Socket s) {
		this.s = s;	
	}
	public void run() {
		try {
			Thread.sleep(5000);
			new FileUpload().upload(s);
			
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		

	}

}

// 1、主程序
public class UploadPicByThread {
	public static void main(String[] args) throws Exception {
		// ①定义服务端点:
		ServerSocket ss = new ServerSocket(10007);
		//②为每一个客户端开启一个
	    int cNum=0;
		while (true) {
			Socket s = ss.accept();
			cNum++;
			new Thread(new UploadThread(s)).start();
			System.out.println("上传成功文件数:"+cNum);
		}

	}
}




4、服务端:业务类,根据不同的上传,选择不同的方式

 

import java.io.*;
import java.net.*;

// 2、业务类
public class FileUpload {

	public void upload(Socket s) {
		try {
			ObjectInputStream ois=new ObjectInputStream(s.getInputStream());
			File file=(File)ois.readObject();
			//当发现文件存在时,修改文件名:如 1.mp3->(count++)1.mp3
			String name=file.getName();//原始文件名
			File dir=new File("D:\\tx\\");
			file=new File(dir,name);
			int count=0;
			while(file.exists()){
				count++;
				file=new File(dir,"("+count+")"+name);
			}
			/*当时文本文件时,调用文本上传方法
			 * 否则调用字符流上传方法
			 */
			
			if(name.endsWith(".txt")){
				textUpload(s,file);
			}else{
				picUpload(s,file);
			}
			
		}  catch (Exception e) {
			System.out.println(e);
			System.out.println("上传失败");
		}
		
	}

	// ①图片等多媒体文件上传(字节流)
	public void picUpload(Socket s, File file)  throws Exception{

			//打印客户端
			String ip=s.getInetAddress().getHostAddress();
			System.out.println(ip+"....connect 准备上传"+file.getName());
			
			FileOutputStream fos = new FileOutputStream(file);
			InputStream in = s.getInputStream();
			OutputStream out = s.getOutputStream();


			// ②读取数据
			int len = 0;
			byte[] buf = new byte[1024 * 2];
			while ((len = in.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
			// ③给客户端反馈
			System.out.println(file.getName()+"服务端接收完成");
			out.write("success".getBytes());
			// 给客户端发送结束标记
			s.shutdownOutput();

			// ④关闭资源
			fos.close();
			s.close();
		

	}

	// ②文本上传(字符流)
	public void textUpload(Socket s, File file) throws Exception {
		
			//打印客户端连接的
			String ip=s.getInetAddress().getHostAddress();
			System.out.println(ip+"....connect 准备上传"+file.getName());
			
			BufferedWriter bufw = new BufferedWriter(new FileWriter(file));
			// Socket 输出输入
			BufferedReader bufin = new BufferedReader(new InputStreamReader(
					s.getInputStream()));
			BufferedWriter bufout = new BufferedWriter(new OutputStreamWriter(
					s.getOutputStream()));

			// ②:读数据、写到文件、判断结束、反馈成功
			String line = null;
			/*
			 * 服务端收不到line=null的情况,必须在流中添加结束标记 s.shutdownOutput();
			 * 关闭客户端的输出流,相当于在流中写-1,line就可以=null
			 */
			// 获取标记符(即时间值)
			while ((line = bufin.readLine()) != null) {
				bufw.write(line);
				bufw.newLine();
				bufw.flush();

			}
			System.out.println(file.getName()+"数据接收成功!");
			bufout.write("success");
			bufout.newLine();
			bufout.flush();
			s.shutdownOutput();

			// 关闭资源
			bufw.close();
			s.close();
		
	}
}