Java中用Socket实现HTTP文件上传实例

发布时间 - 2026-01-11 00:36:06    点击率:

我想做过web开发的程序员大部分都做过文件上传的功能,大多数时候我们都是借助于commons-fileupload这样的jar包实现的。下面我试着通过读取Socket的输入流来实现一个文件上传的功能。

在做文件上传之前我们需要先了解一下HTTP POST的附件上传协议。HTTP附件上传协议是RFC1876协议,RFC1876协议是在HTTP协议的基础上为INPUT标签增加了file属性,同时限定了Form的method必须为POSTENCTYPE必须为multipart/form-data。RFC1867协议对HTTP头作了适当地变更,content-type头由以前的:content-type:application/x-www-form-urlencoded变为content-type:multipart/form-data;+空格+boundary=字符串。RFC1867增加了文件上传得功能,而上传文件内容自然也会被加入到HTTP的实体中。现在因为既有HTTP一般的参数实体,又有上传文件的实体,所以用boundary把每种实体进行了分割。具体的看下图:

接下来就开始我们的代码部分吧。

我在前面的文章中写过创建一个自己的Web服务器,现在我们的重点要放在对socket的输入流的解析中。具体代码如下:

public void parseRequest() { 
  LineNumberReader br = new LineNumberReader(new InputStreamReader(inputStream)); 
  StringBuffer sb = new StringBuffer(); 
  String str = null; 
  try { 
    //读取请求行 
    String requestLine = br.readLine(); 
    if (!StringUtils.isEmpty(requestLine)) { 
      sb.append(requestLine); 
      String[] reqs = requestLine.split(" "); 
      if (reqs != null && reqs.length > 0) { 
        if ("GET".equals(reqs[0])) { 
          method = "GET"; 
        } else { 
          method = "POST"; 
        } 
      } 
    } 
    //读取请求头 
    while ((str = br.readLine()) != null) { 
      if ("".equals(str)) { 
        break; 
      } 
      if (!StringUtils.isEmpty(str)) { 
        if (str.indexOf(":") > 0) { 
          String[] strs = str.split(":"); 
          headers.put(strs[0].toLowerCase(), strs[1].trim()); 
        } 
      } 
      sb.append(str).append("\n"); 
    } 
    //POST请求,Content-type为 multipart/form-data 
    String contentType = null; 
    if ("POST".equals(method) && ((contentType = headers.get("content-type")) != null 
        && headers.get("content-type").startsWith("multipart/form-data"))) { 
      //文件上传的分割位 这里只处理单个文件的上传 
      String boundary = contentType.substring(contentType.indexOf("boundary") + 
          "boundary=".length()); 
      //解析消息体 
      while ((str = br.readLine()) != null) { 
        //解析结束的标记 
        do { 
          //读取boundary中的内容 
          //读取Content-Disposition 
          str = br.readLine(); 
          //说明是文件上传 
          if (str.indexOf("Content-Disposition:") >= 0 && str.indexOf("filename") > 0) { 
            str = str.substring("Content-Disposition:".length()); 
            String[] strs = str.split(";"); 
            String fileName = strs[strs.length - 1].replace("\"", "").split("=")[1]; 
            System.out.println("fileName = " + fileName); 
            //这一行是Content-Type 
            br.readLine(); 
            //这一行是换行 
            br.readLine(); 
            //正式去读文件的内容 
            BufferedWriter bw = null; 
            try { 
              bw = new BufferedWriter(new OutputStreamWriter(new 
                  FileOutputStream("G:\\LearnVideo\\fileLoad" + 
                  File.separator + fileName), "UTF-8")); 
              while (true) { 
                str = br.readLine(); 
                if (str.startsWith("--" + boundary)) { 
                  break; 
                } 
                bw.write(str); 
                bw.newLine(); 
              } 
              bw.flush(); 
            } catch (Exception e) { 
 
            } finally { 
              if (bw != null) { 
                bw.close(); 
              } 
            } 
          } 
          if (str.indexOf("Content-Disposition:") >= 0) { 
            str = str.substring("Content-Disposition:".length()); 
            String[] strs = str.split(";"); 
            String name = strs[strs.length - 1].replace("\"", "").split("=")[1]; 
            br.readLine(); 
            StringBuilder stringBuilder = new StringBuilder(); 
            while (true) { 
              str = br.readLine(); 
              if (str.startsWith("--" + boundary)) { 
                break; 
              } 
              stringBuilder.append(str); 
            } 
            parameters.put(name, stringBuilder.toString()); 
          } 
        } while (("--" + boundary).equals(str)); 
        //解析结束 
        if (str.equals("--" + boundary + "--")) { 
          break; 
        } 
      } 
    } 
    //System.out.println(sb.toString()); 
    //获取URI 
    uri = StringUtils.parserUri(sb.toString(), " "); 
    int flag = -1; 
    //说明有参数 
    if ((flag = uri.indexOf('?')) >= 0) { 
      String oldUri = uri; 
      uri = uri.substring(0,flag); 
      String parameterPath = oldUri.substring(flag+1); 
      String[] parameter = parameterPath.split("&"); 
      if (parameter != null && parameter.length > 0) { 
        for (int i = 0; i < parameter.length; i++) { 
          String str1 = parameter[i]; 
          if((flag = str1.indexOf('=')) >= 0){ 
            String key = str1.substring(0,flag); 
            String value = str1.substring(flag+1); 
            parameters.put(key,value); 
          }else{ 
            parameters.put(str,null); 
          } 
        } 
      } 
    } 
  } catch (IOException e) { 
    e.printStackTrace(); 
  } 
} 

我们启动自己创建的Web服务器,然后在浏览器中输入:http://localhost:8004/static/uploadPage.html,页面如下:

选择我们要上次的文件,然后点击上传按钮,我们会发现我们的功能已经被上传到G:\LearnVideo\fileLoad这个目录下了。示例如下:

完整的代码请从这里下载:FullStackTraining_jb51.rar

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


# socket实现文件上传  # java  # socket实现http  # socket  # http  # 文件上传  # Java 基于TCP Socket 实现文件上传  # Socket+JDBC+IO实现Java文件上传下载器DEMO详解  # Java Socket+mysql实现简易文件上传器的代码  # JavaWeb实现文件上传下载功能实例解析  # JAVA中使用FTPClient实现文件上传下载实例代码  # java实现FTP文件上传与文件下载  # JavaWeb实现文件上传下载功能实例详解  # java web图片上传和文件上传实例  # Java实现文件上传至服务器的方法  # java使用Socket实现文件上传功能  # 上传  # 做过  # 这一行  # 自己的  # 上传文件  # 都是  # 增加了  # 我想  # 是在  # 我在  # 也会  # 又有  # 下了  # 作了  # 在对  # 定了  # 试着  # 来实现  # 这里下载 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel distinct去重查询_Laravel Eloquent去重方法  网站页面设计需要考虑到这些问题  如何自定义safari浏览器工具栏?个性化设置safari浏览器界面教程【技巧】  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  googleplay官方入口在哪里_Google Play官方商店快速入口指南  Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制  Python高阶函数应用_函数作为参数说明【指导】  android nfc常用标签读取总结  详解jQuery中的事件  Laravel Artisan命令怎么自定义_创建自己的Laravel命令行工具完全指南  大同网页,大同瑞慈医院官网?  如何快速搭建高效WAP手机网站吸引移动用户?  bing浏览器学术搜索入口_bing学术文献检索地址  公司门户网站制作公司有哪些,怎样使用wordpress制作一个企业网站?  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱动更新修复【详解】  JS弹性运动实现方法分析  Linux系统运维自动化项目教程_Ansible批量管理实战  微信小程序 配置文件详细介绍  Laravel怎么创建控制器Controller_Laravel路由绑定与控制器逻辑编写【指南】  高端云建站费用究竟需要多少预算?  手机软键盘弹出时影响布局的解决方法  Python3.6正式版新特性预览  Laravel如何发送系统通知?(Notification渠道示例)  php 三元运算符实例详细介绍  制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?  🚀拖拽式CMS建站能否实现高效与个性化并存?  JavaScript如何操作视频_媒体API怎么控制播放  javascript事件捕获机制【深入分析IE和DOM中的事件模型】  Laravel如何安装使用Debugbar工具栏_Laravel性能调试与SQL监控插件【步骤】  详解jQuery停止动画——stop()方法的使用  高配服务器限时抢购:企业级配置与回收服务一站式优惠方案  如何快速辨别茅台真假?关键步骤解析  做企业网站制作流程,企业网站制作基本流程有哪些?  ,网页ppt怎么弄成自己的ppt?  如何获取免费开源的自助建站系统源码?  Laravel Session怎么存储_Laravel Session驱动配置详解  Android中AutoCompleteTextView自动提示  最好的网站制作公司,网购哪个网站口碑最好,推荐几个?谢谢?  深圳网站制作平台,深圳市做网站好的公司有哪些?  Laravel如何构建RESTful API_Laravel标准化API接口开发指南  中国移动官方网站首页入口 中国移动官网网页登录  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  如何在阿里云域名上完成建站全流程?  Laravel怎么自定义错误页面_Laravel修改404和500页面模板  Laravel如何处理文件上传_Laravel Storage门面实现文件存储与管理  Laravel Debugbar怎么安装_Laravel调试工具栏配置指南  如何快速查询网址的建站时间与历史轨迹?  高防服务器租用如何选择配置与防御等级?  创业网站制作流程,创业网站可靠吗?