通过Socket实现文件上传/上传文件

文章目录

  • 整个功能的实现步骤
  • 客户端的实现步骤
  • 服务端的实现步骤
  • 示例代码

整个功能的实现步骤

1.客户端使用本地的字节输入流读取被上传的文件数据
2.客户端使用网络字节输出流,将读取到的文件数据发送给服务端
3.服务端使用网络字节输入流读取客户端发送过来的文件数据
4.服务端使用本地字节输出流将读取到的文件数据写入到指定的服务器本地文件中(例如,保存到目录 upload 下面)
5.服务端使用网络字节输出流,给客户端回写一段文字:“上传成功”
6.客户端使用网络字节输入流,读取服务端返回的数据
7.释放资源

注意:
1.客户端和服务端对本地硬盘进行读写,需要使用自己创建的 IO 流,称为本地流
2.客户端和服务端之间进行数据读写,必须使用 Socket 中提供的 IO 流,称为网络流

客户端的实现步骤

1.创建一个本地字节输入流对象(即 FileInputStream),构造方法中绑定要读取的数据源
2.创建一个客户端对象(即 Socket 对象),构造方法中绑定 IP 和端口号
3.使用 Socket 对象的方法 getOutputStream,获取网络字节输出流对象
4.使用 FileInputStream 对象的方法 read 读取要上传的文件数据
5.使用网络字节输出流对象的方法 write,将读取到的文件数据发送到服务端
6.使用 Socket 对象的方法 getInputStream 获取网络字节输入流对象
7.使用网络字节输入流对象的方法 read 读取服务端回写的数据
8.释放资源(FileInputStream、Socket)

服务端的实现步骤

1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号
2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)
3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流
4.判断服务端的目标目录路径是否存在,若不存在要创建此目录
5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径
6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据
7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中
8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象
9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!
10.释放资源(FileOutputStream、Socket、ServerSocket)

示例代码

客户端代码:

package priv.lwx.javaex.fileupload;import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;/*** @ClassName TCPClient* @Description 客户端读取本地的文件数据,发送给服务端* @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午4:50*/
public class TCPClient {public static void main(String[] args) throws IOException {// 1.创建一个本地字节输入流对象(即 `FileInputStream`),构造方法中绑定要读取的数据源FileInputStream fis = new FileInputStream("/Users/liaowenxiong/desktop/test/1.jpeg");// 2.创建一个客户端对象(即 Socket 对象),构造方法中绑定 IP 和端口号Socket socket = new Socket("127.0.0.1", 8888);// 3.使用 Socket 对象的方法 getOutputStream,获取网络字节输出流对象OutputStream os = socket.getOutputStream();// 4.使用 FileInputStream 对象的方法 read 读取要上传的文件数据byte[] bytes = new byte[1024];int i = 0;while ((i = fis.read(bytes)) != -1) {// 5.使用网络字节输出流对象的方法 write,将读取到的文件数据发送到服务端os.write(bytes, 0, i); // i表示获取数组元素的个数}// 禁用此套接字的输出流,此时会写入一个终止标记,这样服务端就可以读取到此标记,就不会出现阻塞的问题了// 终止标记表示输出流写出的数据已经没有了,服务端解析到这个标记后就,有关的线程就不会一直处于等待接收// 数据的状态socket.shutdownOutput();// 6.使用 Socket 对象的方法 getInputStream 获取网络字节输入流对象InputStream is = socket.getInputStream();// 7.使用网络字节输入流对象的方法 read 读取服务端回写的数据到指定的字节数组中i = is.read(bytes);// 读取几个字节,就返回几// 将字节数组中的数据转换成字符串,并打印到控制台System.out.println(new String(bytes, 0, i));// 8.释放资源(FileInputStream、Socket)fis.close();socket.close();}
}

服务端代码:

package priv.lwx.javaex.fileupload;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;/*** @ClassName TCPServer* @Description 服务端读取客户端发送过来的文件数据,并写入到指定的服务器本地的文件中* @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午7:38*/
public class TCPServer {public static void main(String[] args) throws IOException {// 1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号ServerSocket server = new ServerSocket(8888);// 2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)Socket socket = server.accept();// 3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流InputStream is = socket.getInputStream();// 4.判断服务端的目标目录路径是否存在,若不存在要创建此目录File file = new File("/Users/liaowenxiong/desktop/test/upload");if (!file.exists()) {file.mkdirs();}// 5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径FileOutputStream fos = new FileOutputStream(file + File.separator + "1.jpeg");// 6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据byte[] bytes = new byte[1024];int i = 0;while ((i = is.read(bytes)) != -1) {// 7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中fos.write(bytes, 0, i);}// 8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象OutputStream ops = socket.getOutputStream();// 9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!ops.write("文件上传成功!".getBytes());// 10.释放资源(FileOutputStream、Socket、ServerSocket)fos.close();socket.close();server.close();}}

服务端的升级版本一:

package priv.lwx.javaex.fileupload;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;/*** @ClassName TCPServer* @Description 服务端读取客户端发送过来的文件数据,并写入到指定的服务器本地的文件中*              在 TCPServer 的基础上优化两个地方*              1.自定义文件名,每次上传文件的文件名都不同*              2.让服务端一直处于监听状态,这样就可以一直上传图片** @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午7:38*/
public class TCPServer02 {public static void main(String[] args) throws IOException {// 1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号ServerSocket server = new ServerSocket(8888);// 2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)// 通过死循环,可以让服务端一直处于监听状态,只要有客户端请求连接,服务端就可以响应连接请求while (true) {Socket socket = server.accept();// 3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流InputStream is = socket.getInputStream();// 4.判断服务端的目标目录路径是否存在,若不存在要创建此目录File file = new File("/Users/liaowenxiong/desktop/test/upload");if (!file.exists()) {file.mkdirs();}// 自定义文件名的规则String fileName = System.currentTimeMillis() + (new Random().nextInt(9) + 1) + ".jpeg";// 5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径FileOutputStream fos = new FileOutputStream(file + File.separator + fileName);// 6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据byte[] bytes = new byte[1024];int i = 0;while ((i = is.read(bytes)) != -1) {// 7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中fos.write(bytes, 0, i);}// 8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象OutputStream ops = socket.getOutputStream();// 9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!ops.write("文件上传成功!".getBytes());// 10.释放资源(FileOutputStream、Socket、ServerSocket)fos.close();socket.close();// 服务端不停止,服务端资源不要释放// server.close();}}}

服务端的升级版本二:

package priv.lwx.javaex.fileupload;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;/*** @ClassName TCPServer* @Description 服务端读取客户端发送过来的文件数据,并写入到指定的服务器本地的文件中*              在 TCPServer02 基础上优化*              使用多线程技术,提高程序的效率,有一个客户端上传文件,就开启一个线程完成文件的上传* @Author liaowenxiong* @Version 1.0* @date 2021/9/5 下午7:38*/
public class TCPServer03 {public static void main(String[] args) throws IOException {// 1.创建一个服务端对象(即 ServerSocket),并且向系统要指定的端口号ServerSocket server = new ServerSocket(8888);// 2.使用服务端对象的方法 accept 获取请求的客户端对象(即请求连接的 Socket 对象)// 通过死循环,可以让服务端一直处于监听状态,只要有客户端请求连接,服务端就可以响应连接请求while (true) {Socket socket = server.accept();// 使用多线程技术,提高文件上传的效率,有一个客户端上传文件,就开启一个线程完成文件的上传new Thread(new Runnable() {// run 方法里面完成文件数据的读取和写入@Overridepublic void run() {FileOutputStream fos = null;try {// 3.使用 Socket 对象的方法 getInputStream 获取网络字节输入流InputStream is = socket.getInputStream();// 4.判断服务端的目标目录路径是否存在,若不存在要创建此目录File file = new File("/Users/liaowenxiong/desktop/test/upload");if (!file.exists()) {file.mkdirs();}// 自定义文件名的规则String fileName = System.currentTimeMillis() + (new Random().nextInt(9) + 1) + ".jpeg";// 5.创建一个本地字节输出流对象(即 FileOutputStream),构造方法中要绑定写入数据的目标文件路径fos = new FileOutputStream(file + File.separator + fileName);// 6.使用网络字节输入流的方法 read 读取客户端发送过来的文件数据byte[] bytes = new byte[1024];int i = 0;while ((i = is.read(bytes)) != -1) {// 7.使用 FileOutputStream 对象的方法 write 将读取到文件数据写入到服务器本地文件中fos.write(bytes, 0, i);}// 8.使用 Socket 对象的方法 getOutputStream 获取网络字节输出流对象OutputStream ops = socket.getOutputStream();// 9.使用网络字节输出流对象的方法 write 给客户端发送一段文字:文件上传成功!ops.write("文件上传成功!".getBytes());// 10.释放资源(FileOutputStream、Socket、ServerSocket)} catch (IOException e) {// System.out.println(e);e.printStackTrace();} finally {try {fos.close();socket.close();// 服务端不停止,服务端资源不要释放// server.close();} catch (IOException e) {e.printStackTrace();}}}}).start();}}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/332305.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

构造函数调用默认构造函数_显式无参数构造函数与默认构造函数

构造函数调用默认构造函数大多数不熟悉Java的开发人员都会Swift了解到,如果他们没有指定至少一个显式构造函数,则会为Java类隐式创建一个“ 默认构造函数 ”( 由javac进行创建)。 Java语言规范的 8.8.9节简要指出:“如…

Artifact到底是什么

将项目构建成一个可以在服务器部署的文件包(如:war 包或者 exploded 的文件包),或者构建成的 jar 包(这些 jar 包通常是某些模块程序文件,也可以是某些插件程序文件),这些都叫 Artif…

python win10 桌面_Python3如何实现Win10桌面自动切换

得空写了个自动切换桌面背景图片的小程序。再不写python就要扔键盘了,对vue还有那么一点好感,天天php真是有够烦。准备工作准备个文件夹放在桌面上,平时看到什么高清好图就拽进去。运行脚本脚本如下:#!/usr/bin/pythonimport ctyp…

java中抽象类继承抽象类_用Java中的抽象类扩展抽象类

java中抽象类继承抽象类示例问题 当我创建Java :: Geci抽象类AbstractFieldsGenerator和AbstractFilteredFieldsGenerator我遇到了一个不太复杂的设计问题。 我想强调一下,这个问题和设计对于某些人来说似乎很明显,但是在我最近与一位初级开发人员&#…

pb90代码如何连接sql2008r2_如何使用 HTTP Headers 来保护你的 Web 应用

众所周知,无论是简单的小网页还是复杂的单页应用,Web 应用都是网络攻击的目标。2016 年,这种最主要的攻击模式 —— 攻击 web 应用,造成了大约 40% 的数据泄露。事实上,现在来说,了解网络安全并不是锦上添花…

Servlet配置初始化参数/配置参数

文章目录给某个Servlet配置初始化参数配置全局的参数ServletConfig给某个Servlet配置初始化参数 也可以通过注解的方式来配置初始化参数: 在 Servlet 中获取针对 Servlet 的参数值: String version getInitParameter("version");配置全局的…

poi动态创建文档_POI创建的文档具有不同条件的灵活样式

poi动态创建文档介绍 这篇文章解释了基于各种标准将样式应用于文档的困难并提供了解决方案。 Java编程中的常见任务之一是根据存储在数据库中的数据创建Excel报告。 在这些情况下,Java程序员使用POI :-)。 这些报告通常对样式和数据格式有严格的规定。 数据通常是SQ…

python编码程序_python 编码

网页的编码方式是简体中文gb2312 (查看网页源码,可以看到),而python内部的编码方式为unicode,之前的代码是这样的:contentAll urllib.urlopen(urlLink).read()soup BeautifulSoup.BeautifulSoup(contentAll) #生成BeautifulSou…

比特(bit)_二进制数

二进制数位,也叫比特位,其实就是指位置,是指二进制数的位置。例如,0101 这是二进制数,而且是 4 位的二进制数,因为有 4 个位置,每个位置放一个二进制数,确切的说是每个位置放一个二进…

javax线程池超时结束_没有Javax的Jakarta EE:这次世界也不会结束

javax线程池超时结束如果您错过了新闻, Oracle将向Eclipse基金会捐赠Java EE规范 。 这个决定是在规范过程中进行了相当长时间的Hibernate之后,人们理所当然地怀疑Oracle丧失了对Java EE的战略兴趣。 首先,Java EE和更广泛的Java社区很好地满…

Final Cut Pro X如何去视频水印/视频去水印

先剪辑好视频(比如把不要的段切掉),然后选中视频,把它复制一份到另一个轨道(按住option键,用鼠标左键拖放即可复制)点击右下角的 效果(Effect)→ 模糊(Blur)→ 高斯模糊(Gaussian),把高斯模糊拖入上边那条轨道再次选择效果(Effect…

为什么线程池里的方法会执行两次_面试官问你java都有哪些线程池,自己是否自定义过线程池...

我还记得大学实习面试时,被问到什么是线程池这个问题,因为这个题我被录取了,原因就是我背出来了,而另外一个面试的没背出来,说实话当时还真不知道它是干什么的,就是看面试题给背下来了,在之后就…

java中两任务并行运行_Java并行编程中的“可调用”与“可运行”任务

java中两任务并行运行当我们用Java编写多线程应用程序时,我们倾向于使用“ Runnable ”接口来实现线程类。 您的类必须简单地实现此接口并覆盖run方法。 对于琐碎的用例,我们可以通过调用“ start”方法直接启动线程,结果将控制流委托给run…

Servlet中的监听器

文章目录什么是监听器如何写监听器配置监听器统计在线人数的案例什么是监听器 Servlet 规范当中定义的一种特殊的类,作用是监听容器当中产生的一些事件并进行相应的处理。 容器产生的事件指的是两大类事件: 第一大类 生命周期相关的事件,指…

python调用百度接口实现ocr识别_Python调用百度OCR实现图片文字识别的示例代码

百度AI提供了一天50000次的免费文字识别额度,可以愉快的免费使用!下面直接上方法:首先在百度AI创建一个应用,按照下图创建即可,创建后会获得如下:创建后会获得如下信息:APP_ID ******API_KEY …

selenium 替代品_每个人都在谈论Selenium替代品-明智地选择!

selenium 替代品什么是Selenium? Selenium是一套Web浏览器自动化工具,用于跨多种平台实现浏览器自动化。 尽管Selenium工具具有更多功能,但出于测试原因,它们仍被用来自动化Web应用程序。 Jason Huggins于2004年创建了Selenium&am…

Maven构建Artifact时,不会创建空目录

Maven 构建的 Web 项目中,你在 Web Resource Directories(默认名称是webapp)下创建的空目录,在构建Artifact 时,并不会在构件中也创建该空目录。 下图所示的四个空目录 upload,在构建 Artifact 时都不会创…

通用数据保护条例_欧盟《通用数据保护条例》——2019年的形势

“自欧盟《通用数据保护条例》(GDPR)生效以来,很多公司企业都忙于实行全新的数据保护标准。一个完善的数据保护管理系统比以往任何时候都要重要。我们可以参考一下其他公司在GDPR方面的一些初步经验。”自2018年5月25日GDPR生效以来,它在某些情况下引发了…

【经典LeetCode算法题目专栏分类】【第10期】排序问题、股票问题与TOP K问题:翻转对、买卖股票最佳时机、数组中第K个最大/最小元素

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能AI、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推荐--…

caffeine 缓存_使用Caffeine和Spring Boot的多个缓存配置

caffeine 缓存缓存是几乎所有应用程序性能的关键。 有时需要分布式缓存 ,但并非总是如此。 在许多情况下,本地缓存可以很好地工作,并且不需要分布式缓存的开销和复杂性。 因此,在许多应用程序中,包括普通的Spring和Sp…