这里详细展示了使用TCP协议进行本地图片上传的案例。案例要求:从本地通过客户端向服务器上传一个图片,要求对图片进行判断,是否为“.jpg”格式,大小不能超过2M,服务器将图片保存,并向客户端发送反馈信息。这个案例很多书籍或者网络资源都有所涉及,但是都不算全面。在这里我做了一点小小的改进,一是在客户端中,采用PrintStream打印流将获取到的本地数据发送给服务器端;二是在服务器端中,使用了一个小技巧解决了上传多个重名的文件的问题。
客户端:
public class Cilent { public static void main(String[] args) { //调用方法,对文件进行判断 File file = getFile(); //如果文件不存在,就直接结束主程序 if(file == null){ return; } try (Socket socket = new Socket("127.0.0.1", 8889);//创建客户端 //创建输入流,读取图片信息 BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); //获得客户端的输出流 PrintStream ps = new PrintStream(socket.getOutputStream(), true); //获取客户端的输入流,读取服务端的回送信息 BufferedInputStream bis1 = new BufferedInputStream(socket.getInputStream()) ) { //将本地的图片写入到输出流中 byte[] arr = new byte[1024 * 8]; int b; while ((b = bis.read(arr)) != -1) { ps.write(arr, 0, b); } //文件写出完成后,需要显式的告知服务器端已经完成,否则容易造成图片上传不完整,出现破坏 socket.shutdownOutput(); System.out.println("图片发送成功!"); //读取客户端的回送信息 byte[] arr1 = new byte[1024]; int len = bis1.read(arr1); System.out.println(new String(arr1, 0, len)); //关流 bis1.close(); ps.close(); bis.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } /** * 对键盘录入的图片进行判断的方法 * @return */ public static File getFile() { Scanner sc = new Scanner(System.in); System.out.println("请输入图片路径:"); String directory = sc.nextLine(); File file = new File(directory); if (!(file.exists() && file.isFile())) {//如果是文件不存在或者是文件夹 JOptionPane.showMessageDialog(null, "文件不存在!"); return null; } else if (!file.getName().endsWith(".jpg")) {//如果是文件,但后缀不对 JOptionPane.showMessageDialog(null, "文件格式不对"); return null; } else if (file.length() >= 1024 * 1024 * 2) {//如果大小不对 JOptionPane.showMessageDialog(null, "文件过大,不应超过2M,请重新上传!"); return null; }else{ return file; } } }
服务器端:
public class Server { public static void main(String[] args) throws IOException { System.out.println("服务器启动,准备接收文件......"); //创建客户端,指定监视端口 ServerSocket serverSocket = new ServerSocket(8889); //不断创建连接,采用while循环 while (true) { //建立连接 Socket accept = serverSocket.accept(); //采用多线程,lambda表达式形式 new Thread(() -> { //获取客户端的ip地址 String ip = accept.getInetAddress().getHostAddress(); System.out.println(ip + "发来图片...."); //创建图片的保存路径目录 File dir = new File("E:\\test\\pic"); if (!dir.exists()) { dir.mkdirs(); } //通过父目录和子文件名称创建文件,通过系统时间来避免文件重名的情况 File file = new File(dir, System.currentTimeMillis() + ".jpg"); int count = 1; while (file.exists()) { file = new File(dir, System.currentTimeMillis() + "(" + (count++) + ")" + ".jpg"); } try ( //获取服务器端的输入流 BufferedInputStream bis = new BufferedInputStream(accept.getInputStream()); //创建图片输出路径的输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); //获取服务器端的输出流 PrintStream ps = new PrintStream(accept.getOutputStream(), true); ) { //读取输入流中的数据,写入到输出流指定位置文件中 byte[] arr = new byte[1024 * 8]; int b; while ((b = bis.read(arr)) != -1) { bos.write(arr, 0, b); //不断刷新 bos.flush(); } ps.println("服务器端: 第" + (count++) + "张图片已上传成功,保存到服务器"); ps.close(); bos.close(); bis.close(); accept.close(); System.out.println("上传成功!"); } catch (IOException e) { e.printStackTrace(); } }).start(); } } }