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


相关推荐: 如何在香港服务器上快速搭建免备案网站?  电商网站制作价格怎么算,网上拍卖流程以及规则?  jQuery validate插件功能与用法详解  香港服务器网站推广:SEO优化与外贸独立站搭建策略  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  学生网站制作软件,一个12岁的学生写小说,应该去什么样的网站?  高防网站服务器:DDoS防御与BGP线路的AI智能防护方案  Laravel如何自定义分页视图?(Pagination示例)  如何在IIS管理器中快速创建并配置网站?  Laravel怎么做数据加密_Laravel内置Crypt门面的加密与解密功能  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决  laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法  关于BootStrap modal 在IOS9中不能弹出的解决方法(IOS 9 bootstrap modal ios 9 noticework)  Laravel怎么实现观察者模式Observer_Laravel模型事件监听与解耦开发【指南】  EditPlus中的正则表达式 实战(4)  车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?  Laravel如何使用软删除(Soft Deletes)功能_Eloquent软删除与数据恢复方法  C#如何调用原生C++ COM对象详解  如何续费美橙建站之星域名及服务?  Android GridView 滑动条设置一直显示状态(推荐)  php json中文编码为null的解决办法  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  Laravel如何实现数据导出到CSV文件_Laravel原生流式输出大数据量CSV【方案】  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层  ,南京靠谱的征婚网站?  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  如何彻底删除建站之星生成的Banner?  Python数据仓库与ETL构建实战_Airflow调度流程详解  如何用虚拟主机快速搭建网站?详细步骤解析  悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】  UC浏览器如何切换小说阅读源_UC浏览器阅读源切换【方法】  HTML透明颜色代码在Angular里怎么设置_Angular透明颜色使用指南【详解】  JS去除重复并统计数量的实现方法  北京网站制作公司哪家好一点,北京租房网站有哪些?  php在windows下怎么调试_phpwindows环境调试操作说明【操作】  如何在宝塔面板中修改默认建站目录?  MySQL查询结果复制到新表的方法(更新、插入)  HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】  悟空识字如何进行跟读录音_悟空识字开启麦克风权限与录音  新三国志曹操传主线渭水交兵攻略  Laravel如何实现本地化和多语言支持_Laravel多语言配置与翻译文件管理  如何在万网利用已有域名快速建站?  三星网站视频制作教程下载,三星w23网页如何全屏?  IOS倒计时设置UIButton标题title的抖动问题  如何撰写建站申请书?关键要点有哪些?  简历在线制作网站免费版,如何创建个人简历?  Win11搜索栏无法输入_解决Win11开始菜单搜索没反应问题【技巧】  Laravel如何实现RSS订阅源功能_Laravel动态生成网站XML格式订阅内容【教程】