编写Java程序,实现客户端向服务端上传文件的功能

简介: 编写Java程序,实现客户端向服务端上传文件的功能

需求说明:


实现客户端向服务端上传文件的功能

当启动服务端后,运行客户端程序,系统提示客户在客户端输入上传文件的完整路径。当客户在客户端输入完成后,服务端实现文件上传


43.png

44.png


实现思路:


创建客户端类 FileClient 和服务端类 FileServer

在客户端类中定义uploadFile(Socket socket)方法,用于上传文件,使用BufferedOutputStream包装socket中输入流对象,使用new FileInputStream输入流对象读取本地文件,使用输出流将文件利用socket管道将数据循环发送至服务端

在客户端FileCliet类中,使用new Socket连接本地服务端和端口,调用uploadFile方法实现文件上传

在服务端类FileServer中,定义downFile()方法用于下载文件,该方法中使用BufferedInputStream包装socket中的输入流读取文件内容,并且使用FileOutputStream写到本地

分别运行服务端和客户端程序进行测试


实现代码:


服务端类 FileServer

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class FileServer {
  public ServerSocket server;
  public Socket socket;
  public void downloadFile() {
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    try {
      // 获取Socket管道字节输入流
      InputStream in = socket.getInputStream();
      // 将Socket管道字节输入流,进行缓冲包装提高读取的速度
      bis = new BufferedInputStream(in);
      // 读取客户端发送的文件名
      int length = bis.read();
      byte[] b = new byte[length];
      bis.read(b);
      // 获取需要下载的文件名
      String fileName = this.getFileName(new String(b));
      // 下载的文件对象
      FileOutputStream fos = new FileOutputStream("H://" + this.getFileName(fileName));
      // 对FileOutputStream进行缓冲包装,提高写入的速度
      bos = new BufferedOutputStream(fos);
      // 创建临时变量保存数据
      int data = 0;
      // 写入文件
      while ((data = bis.read()) != -1) {
        bos.write(data);
      }
      System.out.println("客户/" + socket.getInetAddress() + ":上传文件[" + fileName + "]成功");
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        if (bis != null) {
          bis.close();
        }
        if (bos != null) {
          bos.close();
        }
        server.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  // 对文件的全路径进行拆分,返回文件名
  private String getFileName(String fn) {
    String[] files = fn.split("/");
    return files[files.length - 1];
  }
  // 创建服务器
  public void crateServer() {
    try {
      // 创建Socket实例
      server = new ServerSocket(8888);
      // 创建while循环接受多个客户端的连接
      while (true) {
        // 每一个连接的客户端都与服务器维护一条专属的Socket通信管道
        socket = server.accept();
        System.out.println("客户端已经连接");
        downloadFile();
        break;
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  public static void main(String[] args) {
    new FileServer().crateServer();
  }
}


客户端类 FileClient


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
public class FileClient {
  // 向服务器发送数据
  public void uploadFile(Socket socket) {
    BufferedReader reader = null;
    BufferedInputStream bis = null;
    BufferedOutputStream bos = null;
    try {
      System.out.println("请输入要上传文件的完成路径:");
      // 接收键盘输入
      InputStream in = System.in;
      // 获取Socket管道字节输出流
      OutputStream out = socket.getOutputStream();
      // 使用BufferedReader包装,便于按行读取客户端输入的数据
      reader = new BufferedReader(new InputStreamReader(in));
      // 客户端上传到服务端文件的名字
      String fileName = reader.readLine();
      // 创建字符文件输入流,用于读取上传文件中的数据
      FileInputStream fis = new FileInputStream(fileName);
      // 使用字节输入缓冲提高读取的速度
      bis = new BufferedInputStream(fis);
      // 获取Socket管道输出流,将从文件中的数据写入到管道中
      bos = new BufferedOutputStream(out);
      byte[] nbt = fileName.getBytes();
      // 将文件名字符串转换成字节数组的长度写入到Socket管道中
      bos.write(nbt.length);
      // 将字节数组写入到Socket管道中
      bos.write(nbt);
      // 定义临时变量,将从文件中读取到的数据写入到Socket管道中
      int data = 0;
      // 将文件中的数据写入到Socket管道中
      while ((data = bis.read()) != -1) {
        bos.write(data);
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      // 关闭io流和socket
      try {
        if (reader != null) {
          reader.close();
        }
        if (bis != null) {
          bis.close();
        }
        if (bos != null) {
          bos.close();
        }
        socket.close();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }
  public static void main(String[] args) {
    Socket client = null;
    try {
      // 创建客户端套接字对象
      client = new Socket("127.0.0.1", 8888);
      new FileClient().uploadFile(client);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
相关文章
|
24天前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
86 34
|
2月前
|
安全 Java 测试技术
🎉Java零基础:全面解析枚举的强大功能
【10月更文挑战第19天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
123 60
|
2月前
|
IDE Java 编译器
开发 Java 程序一定要安装 JDK 吗
开发Java程序通常需要安装JDK(Java Development Kit),因为它包含了编译、运行和调试Java程序所需的各种工具和环境。不过,某些集成开发环境(IDE)可能内置了JDK,或可使用在线Java编辑器,无需单独安装。
84 1
|
2月前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
37 2
|
2月前
|
存储 Java API
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
Java实现导出多个excel表打包到zip文件中,供客户端另存为窗口下载
81 4
|
2月前
|
SQL 安全 Java
Java 异常处理:筑牢程序稳定性的 “安全网”
本文深入探讨Java异常处理,涵盖异常的基础分类、处理机制及最佳实践。从`Error`与`Exception`的区分,到`try-catch-finally`和`throws`的运用,再到自定义异常的设计,全面解析如何有效管理程序中的异常情况,提升代码的健壮性和可维护性。通过实例代码,帮助开发者掌握异常处理技巧,确保程序稳定运行。
46 0
|
3月前
|
Java Maven 数据安全/隐私保护
如何实现Java打包程序的加密代码混淆,避免被反编译?
【10月更文挑战第15天】如何实现Java打包程序的加密代码混淆,避免被反编译?
324 2
|
3月前
|
Java 程序员
在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。
【10月更文挑战第13天】在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。本文介绍了Java关键字的基本概念及其重要性,并通过定义类和对象、控制流程、访问修饰符等示例,展示了关键字的实际应用。掌握这些关键字,是成为优秀Java程序员的基础。
36 3
|
3月前
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
200 1
|
8天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者