最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中用Socket實現(xiàn)HTTP文件上傳實例

 更新時間:2017年04月11日 09:58:37   作者:木葉之榮  
本篇文章主要介紹了Java中用Socket實現(xiàn)HTTP文件上傳實例,詳細的介紹了通過讀取Socket的輸入流來實現(xiàn)一個文件上傳的功能,有興趣的同學可以一起了解一下

我想做過web開發(fā)的程序員大部分都做過文件上傳的功能,大多數(shù)時候我們都是借助于commons-fileupload這樣的jar包實現(xiàn)的。下面我試著通過讀取Socket的輸入流來實現(xiàn)一個文件上傳的功能。

在做文件上傳之前我們需要先了解一下HTTP POST的附件上傳協(xié)議。HTTP附件上傳協(xié)議是RFC1876協(xié)議,RFC1876協(xié)議是在HTTP協(xié)議的基礎上為INPUT標簽增加了file屬性,同時限定了Form的method必須為POST,ENCTYPE必須為multipart/form-data。RFC1867協(xié)議對HTTP頭作了適當?shù)刈兏?,content-type頭由以前的:content-type:application/x-www-form-urlencoded變?yōu)?code>content-type:multipart/form-data;+空格+boundary=字符串。RFC1867增加了文件上傳得功能,而上傳文件內容自然也會被加入到HTTP的實體中?,F(xiàn)在因為既有HTTP一般的參數(shù)實體,又有上傳文件的實體,所以用boundary把每種實體進行了分割。具體的看下圖:

接下來就開始我們的代碼部分吧。

我在前面的文章中寫過創(chuàng)建一個自己的Web服務器,現(xiàn)在我們的重點要放在對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; 
    //說明有參數(shù) 
    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(); 
  } 
} 

我們啟動自己創(chuàng)建的Web服務器,然后在瀏覽器中輸入:http://localhost:8004/static/uploadPage.html,頁面如下:

選擇我們要上次的文件,然后點擊上傳按鈕,我們會發(fā)現(xiàn)我們的功能已經被上傳到G:\LearnVideo\fileLoad這個目錄下了。示例如下:

完整的代碼請從這里下載:FullStackTraining_jb51.rar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • java實現(xiàn)將字符串中首字母轉換成大寫,其它全部轉換成小寫的方法示例

    java實現(xiàn)將字符串中首字母轉換成大寫,其它全部轉換成小寫的方法示例

    這篇文章主要介紹了java實現(xiàn)將字符串中首字母轉換成大寫,其它全部轉換成小寫的方法,涉及java字符串遍歷、轉換、拼接等相關操作技巧,需要的朋友可以參考下
    2019-06-06
  • 23種設計模式(19)java責任鏈模式

    23種設計模式(19)java責任鏈模式

    這篇文章主要為大家詳細介紹了23種設計模式之java責任鏈模式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • 詳解Spring 中如何控制2個bean中的初始化順序

    詳解Spring 中如何控制2個bean中的初始化順序

    本篇文章主要介紹了Spring 中如何控制2個bean中的初始化順序,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    SpringBoot中Shiro緩存使用Redis、Ehcache的方法

    這篇文章主要介紹了SpringBoot中Shiro緩存使用Redis、Ehcache的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-09-09
  • spring boot 不連接數(shù)據庫啟動的解決

    spring boot 不連接數(shù)據庫啟動的解決

    這篇文章主要介紹了spring boot 不連接數(shù)據庫啟動的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java 常見的限流算法詳細分析并實現(xiàn)

    Java 常見的限流算法詳細分析并實現(xiàn)

    大數(shù)據量高并發(fā)訪問時,經常出現(xiàn)服務或接口面對暴漲的請求而不可用的情況,甚至引發(fā)連鎖反映導致整個系統(tǒng)崩潰。此時你需要使用的技術手段之一就是限流,當請求達到一定的并發(fā)數(shù)或速率,就進行等待、排隊、降級、拒絕服務等。限流時,常見算法是計數(shù)器、漏斗、令牌桶算法
    2022-04-04
  • Java面試題沖刺第十五天--設計模式

    Java面試題沖刺第十五天--設計模式

    這篇文章主要為大家分享了最有價值的三道關于設計模式的面試題,涵蓋內容全面,包括數(shù)據結構和算法相關的題目、經典面試編程題等,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 深入了解Spring中最常用的11個擴展點

    深入了解Spring中最常用的11個擴展點

    我們一說到spring,可能第一個想到的是?IOC(控制反轉)?和?AOP(面向切面編程)。除此之外,我們在使用spring的過程中,有沒有發(fā)現(xiàn)它的擴展能力非常強。今天就來跟大家一起聊聊,在Spring中最常用的11個擴展點
    2022-09-09
  • SpringBoot集成kaptcha驗證碼

    SpringBoot集成kaptcha驗證碼

    這篇文章主要為大家詳細介紹了SpringBoot集成kaptcha驗證碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • spring?controller層引用service報空指針異常nullpointExceptio問題

    spring?controller層引用service報空指針異常nullpointExceptio問題

    這篇文章主要介紹了spring?controller層引用service報空指針異常nullpointExceptio問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評論

新和县| 澄江县| 九龙坡区| 阿巴嘎旗| 南雄市| 株洲县| 贡嘎县| 镇远县| 通河县| 北安市| 阳曲县| 米脂县| 红河县| 万安县| 桐城市| 苏尼特左旗| 霍山县| 紫云| 原平市| 蒲城县| 子长县| 兰考县| 永胜县| 洪江市| 吕梁市| 浦北县| 新余市| 翼城县| 那坡县| 孟村| 成都市| 顺平县| 汝阳县| 武定县| 陵水| 扶风县| 伊吾县| 许昌县| 泾川县| 丽水市| 金阳县|