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();
}
}
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客户连接上来后,
*被服务器接收后, 服务端执行具体流程中,这时,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();
}
}