欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

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

接下來(lái)就開(kāi)始我們的代碼部分吧。

我在前面的文章中寫(xiě)過(guò)創(chuàng)建一個(gè)自己的Web服務(wù)器,現(xiàn)在我們的重點(diǎn)要放在對(duì)socket的輸入流的解析中。具體代碼如下:

public void parseRequest() { 
  LineNumberReader br = new LineNumberReader(new InputStreamReader(inputStream)); 
  StringBuffer sb = new StringBuffer(); 
  String str = null; 
  try { 
    //讀取請(qǐng)求行 
    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"; 
        } 
      } 
    } 
    //讀取請(qǐng)求頭 
    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請(qǐng)求,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"))) { 
      //文件上傳的分割位 這里只處理單個(gè)文件的上傳 
      String boundary = contentType.substring(contentType.indexOf("boundary") + 
          "boundary=".length()); 
      //解析消息體 
      while ((str = br.readLine()) != null) { 
        //解析結(jié)束的標(biāo)記 
        do { 
          //讀取boundary中的內(nèi)容 
          //讀取Content-Disposition 
          str = br.readLine(); 
          //說(shuō)明是文件上傳 
          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(); 
            //正式去讀文件的內(nèi)容 
            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)); 
        //解析結(jié)束 
        if (str.equals("--" + boundary + "--")) { 
          break; 
        } 
      } 
    } 
    //System.out.println(sb.toString()); 
    //獲取URI 
    uri = StringUtils.parserUri(sb.toString(), " "); 
    int flag = -1; 
    //說(shuō)明有參數(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(); 
  } 
} 

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

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

完整的代碼請(qǐng)從這里下載:FullStackTraining_jb51.rar

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot基于Swagger2構(gòu)建API文檔過(guò)程解析

    SpringBoot基于Swagger2構(gòu)建API文檔過(guò)程解析

    這篇文章主要介紹了SpringBoot基于Swagger2構(gòu)建API文檔過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java從List中刪除元素的幾種方式小結(jié)

    Java從List中刪除元素的幾種方式小結(jié)

    在Java中,List 接口提供了一個(gè) remove(Object o) 方法來(lái)移除列表中與給定對(duì)象相等的第一個(gè)元素,然而,直接使用這個(gè)方法來(lái)刪除列表中的元素有時(shí)并不是最優(yōu)的選擇,主要原因包括效率和同步性問(wèn)題,本文介紹了Java從List中刪除元素的幾種方式,需要的朋友可以參考下
    2024-08-08
  • SpringBoot動(dòng)態(tài)定時(shí)任務(wù)實(shí)現(xiàn)與應(yīng)用詳解

    SpringBoot動(dòng)態(tài)定時(shí)任務(wù)實(shí)現(xiàn)與應(yīng)用詳解

    定時(shí)任務(wù)在許多應(yīng)用場(chǎng)景中是必不可少的,特別是在自動(dòng)化任務(wù)執(zhí)行、定期數(shù)據(jù)處理等方面,定時(shí)任務(wù)能極大地提高系統(tǒng)的效率,然而,隨著業(yè)務(wù)需求的變化,定時(shí)任務(wù)的執(zhí)行頻率或時(shí)間點(diǎn)可能需要?jiǎng)討B(tài)調(diào)整,所以本文給大家介紹了SpringBoot動(dòng)態(tài)定時(shí)任務(wù)實(shí)現(xiàn)與應(yīng)用
    2024-08-08
  • Java之線(xiàn)程池使用與原理全面解析

    Java之線(xiàn)程池使用與原理全面解析

    這篇文章主要介紹了Java之線(xiàn)程池使用與原理全面解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • 拉鉤網(wǎng)java筆試題分享

    拉鉤網(wǎng)java筆試題分享

    這篇文章主要介紹了拉鉤網(wǎng)java筆試題分享,下面是題目和實(shí)現(xiàn)示例,需要的朋友可以參考下
    2014-05-05
  • Java?Jar包項(xiàng)目?jī)?nèi)存設(shè)置方法舉例

    Java?Jar包項(xiàng)目?jī)?nèi)存設(shè)置方法舉例

    這篇文章主要給大家介紹了關(guān)于Java?Jar包項(xiàng)目?jī)?nèi)存設(shè)置方法的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2024-01-01
  • java 根據(jù)漢字生成拼音全拼或拼音首字母的示例

    java 根據(jù)漢字生成拼音全拼或拼音首字母的示例

    這篇文章主要介紹了java 根據(jù)漢字生成拼音全拼或拼音首字母的示例,幫助大家更好的利用Java處理數(shù)據(jù),感興趣的朋友可以了解下
    2020-11-11
  • Netty實(shí)戰(zhàn)源碼解析NIO編程

    Netty實(shí)戰(zhàn)源碼解析NIO編程

    這篇文章主要為大家介紹了Netty實(shí)戰(zhàn)源碼解析NIO編程的核心組件及關(guān)系詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Java超詳細(xì)講解類(lèi)的繼承

    Java超詳細(xì)講解類(lèi)的繼承

    繼承就是可以直接使用前輩的屬性和方法。自然界如果沒(méi)有繼承,那一切都是處于混沌狀態(tài)。多態(tài)是同一個(gè)行為具有多個(gè)不同表現(xiàn)形式或形態(tài)的能力。多態(tài)就是同一個(gè)接口,使用不同的實(shí)例而執(zhí)行不同操作
    2022-04-04
  • MyBatis與Hibernate的比較

    MyBatis與Hibernate的比較

    Hibernate 與Mybatis都是流行的持久層開(kāi)發(fā)框架,但Hibernate開(kāi)發(fā)社區(qū)相對(duì)多熱鬧些,支持的工具也多,更新也快,當(dāng)前最高版本4.1.8。而Mybatis相對(duì)平靜,工具較少,當(dāng)前最高版本3.2
    2016-01-01

最新評(píng)論