C/S+P2P网络模型(二)--上传&下载文件
2015-01-09 13:46
225 查看
原文地址:http://blog.csdn.net/whoami021/article/details/21656875
上一篇文章我们实现聊天的功能,下面我们看文件传输怎么实现。 我的做法是:增加一个文件服务器,所有上传和下载文件的操作都由文件服务器来处理。 因此处理逻辑是这样的:如果用户请求上传文件或者下载文件,那么就将用户直接与文件服务器通信,而不用经过中央服务器。 所以现在的问题是知道java怎么实现上传和下载文件,如果这个问题解决了,那基本就搞定了。 首先,文件传输基本都是用面向连接的方式。因为无连接的方式容易丢包,一旦丢了一个数据包,文件就坏了,所有努力全白费。但是需要注意的是面向连接的方式,在服务器处理完一个连接后该连接就关闭了。 下面看代码,在原来的基础上我新建了两个主要文件:FileServer.java和FileClient..java。 [java] view plaincopy package chat.net.file; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.Iterator; import java.util.Set; import java.util.TreeMap; import chat.Globals; /** * 文件服务器 * * @author michael * */ public class FileServer { private TreeMap<String, String> fileMap = new TreeMap<>(); private final String SavePath = "save/";// 上传文件保存目录 private final int port = 8821; private ServerSocket ss; private Socket s; private String sender;// 上传者名字 private String receiver;// 接收者名字 private int bufferSize = 8192; public void start() { try { // 创建目录 File file = new File(SavePath); if (!file.exists()) { file.mkdir(); } ss = new ServerSocket(port); while (true) { s = ss.accept(); DataInputStream dis = new DataInputStream( new BufferedInputStream(s.getInputStream())); dis.readByte();// 运行环境 int req = dis.readInt(); if (req == Globals.UploadReq) {// 用户上传文件 recvFile(dis); } else {// 用户下载文件 sendFile(dis); } } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void recvFile(DataInputStream dis) { DataOutputStream dos = null; try { sender = dis.readUTF();// 发送者名字 String savePath = SavePath; byte[] buf = new byte[bufferSize]; long len = 0; String fileName = dis.readUTF();// 可能接收到终止的通知 if (fileName.equals(String.valueOf(Globals.Exit))) { dis.close(); return; } savePath += fileName; dos = new DataOutputStream(new BufferedOutputStream( new BufferedOutputStream(new FileOutputStream(savePath)))); len = dis.readLong(); System.out.println("文件的长度为:" + len); while (true) { int read = 0; if (dis != null) { read = dis.read(buf); } if (read == -1) { break; } dos.write(buf, 0, read); } fileMap.put(fileName, sender); System.out.println("接收完成,文件存为" + savePath); } catch (Exception e) { e.printStackTrace(); } finally { try { dis.close(); if (dos != null) { dos.close(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private void sendFile(DataInputStream dis) { DataOutputStream dos = null; DataInputStream fis = null; try { receiver = dis.readUTF(); dos = new DataOutputStream(s.getOutputStream()); // 给客户端发送文件列表 String fileList = "文件列表:\n"; if (fileMap.size() == 0) { dos.writeUTF(""); return; } Set<String> set = fileMap.keySet(); Iterator<String> it = set.iterator(); String key; int i = 0; while (it.hasNext()) { ++i; key = it.next(); fileList += i + ".<" + key + "," + fileMap.get(key) + ">"; } dos.writeUTF(fileList); String fileName = getFileName(fileList, dis.readInt()); File file = new File(SavePath + fileName); // 开始发送文件 fis = new DataInputStream(new BufferedInputStream( new FileInputStream(file))); dos.writeUTF(fileName); dos.flush(); dos.writeLong((long) file.length()); dos.flush(); byte[] buf = new byte[bufferSize]; int read = 0; while (true) { read = fis.read(buf); if (read == -1) { break; } dos.write(buf, 0, read); } dos.flush(); System.out.println("文件" + fileName + "传输完成"); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { try { dis.close(); if (fis != null) { fis.close(); } dos.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } private String getFileName(String fileList, int no) { String fileName = fileList.substring(fileList.indexOf(String .valueOf(no))); fileName = fileName.substring(fileName.indexOf("<") + 1, fileName.indexOf(",")); return fileName; } public static void main(String[] args) { new FileServer().start(); } } [java] view plaincopy package chat.net.file; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.util.Scanner; import chat.Globals; /** * 文件客户端 支持上传和下载文件 * * @author michael * */ public class FileClient { private String HOST = "127.0.0.1"; private final int port = 8821; private Socket socket; private String ENV = "linux";// 运行环境 private int bufferSize = 8192; private Scanner sc = new Scanner(System.in); /** * 上传文件 * * @param req * @param peer */ public void uploadFile(int req, String peer) { try { socket = new Socket(HOST, port); sendMessage(req, peer);// 发送操作类型 System.out.print("输入上传文件的绝对路径:"); String path = sc.next(); // String path = "/home/michael/Desktop/zouning71.rar"; // 发送文件 File file = new File(path); DataInputStream dis = new DataInputStream(new BufferedInputStream( new FileInputStream(file))); DataOutputStream dos = new DataOutputStream( socket.getOutputStream()); if (!file.exists()) { System.out.println("该文件不存在"); dos.writeUTF(String.valueOf(Globals.Exit)); dos.flush(); return; } sendFile(dis, dos, file); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } private void sendFile(DataInputStream dis, DataOutputStream dos, File file) { try { // 将文件名及长度发给服务器 dos.writeUTF(file.getName()); dos.flush(); dos.writeLong((long) file.length()); dos.flush(); byte[] buf = new byte[bufferSize]; int read = 0; while (true) { read = dis.read(buf); if (read == -1) { break; } dos.write(buf, 0, read); } dos.flush(); // 注意关闭socket链接,不然客户端会等待server的数据过来, // 直到socket超时,导致数据不完整。 dis.close(); dos.close(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } /** * 下载文件 * * @param req * @param peer */ public void downloadFile(int req, String peer) { try { socket = new Socket(HOST, port); sendMessage(req, peer);// 发送操作类型 DataInputStream dis = new DataInputStream(socket.getInputStream()); DataOutputStream dos = new DataOutputStream( socket.getOutputStream()); // 接收文件列表 String fileList = dis.readUTF(); if (fileList.equals("")) { System.out.println("服务器没有文件"); return; } System.out.println(fileList); System.out.print("输入要下载的文件序号:"); dos.writeInt(sc.nextInt()); dos.flush(); System.out.print("输入文件的保存位置(绝对路径):"); String savePath = sc.next(); // String savePath = "/home/michael/Desktop/"; recvFile(dis, dos, savePath); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } private void sendMessage(int req, String peer) { DataOutputStream dos = null; try { dos = new DataOutputStream(socket.getOutputStream()); if (ENV.equalsIgnoreCase("windows")) { dos.writeByte(0x1); dos.flush(); } else if (ENV.equalsIgnoreCase("unix")) { dos.writeByte(0x2); dos.flush(); } else if (ENV.equalsIgnoreCase("linux")) { dos.write(0x3); dos.flush(); } else { dos.writeUTF(ENV); dos.flush(); } dos.writeInt(req);// 向服务器发送操作类型:上传文件OR下载文件 dos.writeUTF(peer);// 上传者或者下载者 dos.flush(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void recvFile(DataInputStream dis, DataOutputStream dos, String savePath) { try { byte[] buf = new byte[bufferSize]; long len = 0; String fileName = dis.readUTF(); if (!savePath.endsWith("/")) { savePath += "/"; } savePath += fileName; dos = new DataOutputStream(new BufferedOutputStream( new BufferedOutputStream(new FileOutputStream(savePath)))); len = dis.readLong(); System.out.println("文件的长度为:" + len); int read = 0; while (true) { read = dis.read(buf); if (read == -1) { break; } dos.write(buf, 0, read); } System.out.println("接收完成,文件存为" + savePath); dis.close(); dos.close(); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { FileClient client = new FileClient(); client.uploadFile(Globals.UploadReq, "noname"); client.downloadFile(Globals.DownloadReq, "noname"); } } 上面这两个文件就可以实现文件上传和下载了,有需要完整工程代码的请点击这里。 测试的时候先运行两个服务器:Server和FileServer,然后在运行Main。
相关文章推荐
- C/S+P2P网络模型(二)--上传&下载文件
- iOS 开发之网络——文件上传&文件下载
- Android开发之网络请求通信专题(二):基于HttpClient的文件上传下载
- 文件上传与下载—>struts
- 实时开发框架Meteor 实际应用系列<一>---文件的上传和下载
- phonegap文件,目录操作以及网络上传,下载文件(含demo)
- java 简单的文件上传下载服务器模型(IO + 多线程)
- window xp 使用SecureCRT上传和下载文件 && 中文乱码处理
- phonegap文件,目录操作以及网络上传,下载文件(含demo)
- 网络编程之get,post请求,文件上传及下载
- Struts2 Chapter7 国际标签&文件的上传和下载
- 利用ASIHttp实现文件的下载、上传和网络状态的监控
- Struts2 Chapter 7&8 :文件的上传和下载,图形报表的生成part1
- putty windows上传文件到linux服务器 & 从linux服务器 下载文件到 windows
- [iOS 多线程 & 网络 - 2.10] - ASI框架下载文件
- java网络编程和io,多线程结合完成文件上传和下载案例
- 文件的上传与下载--->张国亮总结心得第一季
- OK6410开发板uboot 网络移植及通过交叉网线上传下载文件
- response.sendRedirect("")与文件上传下载
- SharePoint 2010开发实例精选——通过客户端对象模型上传下载文件