2015-10-27 66 views
4

我的工作在具有HTTP服務器內置的Java應用程序,此刻的服務器使用的ServerSocketChannel實現的,它偵聽端口1694的請求:Java的HTTP服務器發送分塊響應

 msvrCh = ServerSocketChannel.open(); 
     msvrCh.socket().bind(new InetSocketAddress(mintPort)); 
     msvrCh.configureBlocking(false); 

一螺紋安裝管理請求和響應:

 Thread thrd = new Thread(msgReceiver); 
     thrd.setUncaughtExceptionHandler(exceptionHandler); 
     thrd.start(); 

線程很簡單:

 Runnable msgReceiver = new Runnable() { 
      @Override 
      public void run() { 
       try{ 
        while(!Thread.interrupted()) { 
    //Sleep a short period between checks for new requests       
         try{ 
          Thread.sleep(DELAY_BETWEEN_ACCEPTS); 
         } catch(Exception ex) { 
          ex.printStackTrace(); 
         }       
         SocketChannel cliCh = msvrCh.accept(); 

         if (blnExit() == true) { 
          break; 
         }       
         if (cliCh == null) { 
          continue; 
         } 
         processRequest(cliCh.socket()); 
        }      
       } catch (IOException ex) { 
        ex.printStackTrace(); 
       } finally {      
        logMsg(TERMINATING_THREAD + 
          "for accepting cluster connections", true); 

        if (msvrCh != null) { 
         try { 
          msvrCh.close(); 
         } catch (IOException ex) { 
          ex.printStackTrace(); 
         } 
         msvrCh = null; 
        } 
       }    
      } 
     }; 

主要散裝用於處理所述響應代碼是在功能的processRequest:

private void processRequest(Socket sck) { 
    try { 
    //AJAX Parameters 
     final String AJAX_ID   = "ajmid"; 
    //The 'Handler Key' used to decode response   
     final String HANDLER_KEY  = "hkey"; 
    //Message payload   
     final String PAYLOAD   = "payload"; 
    //Post input buffer size    
     final int REQUEST_BUFFER_SIZE = 4096; 
    //Double carriage return marks the end of the headers   
     final String CRLF    = "\r\n"; 

     BufferedReader in = new BufferedReader(new InputStreamReader(sck.getInputStream())); 
     String strAMID = null, strHKey = null, strRequest; 
     char[] chrBuffer = new char[REQUEST_BUFFER_SIZE]; 
     StringBuffer sbRequest = new StringBuffer(); 
     eMsgTypes eType = eMsgTypes.UNKNOWN; 
     clsHTTPparameters objParams = null; 
     int intPos, intCount;    
    //Extract the entire request, including headers   
     if ((intCount = in.read(chrBuffer)) == 0) { 
      throw new Exception("Cannot read request!"); 
     } 
     sbRequest.append(chrBuffer, 0, intCount);   
     strRequest = sbRequest.toString(); 
    //What method is being used by this request? 
     if (strRequest.startsWith(HTTP_GET)) { 
    //The request should end with a HTTP marker, remove this before trying to interpret the data 
      if (strRequest.indexOf(HTTP_MARKER) != -1) { 
       strRequest = strRequest.substring(0, strRequest.indexOf(HTTP_MARKER)).trim(); 
      }    
    //Look for a data marker 
      if ((intPos = strRequest.indexOf(HTTP_DATA_START)) >= 0) { 
    //Data is present in the query, skip to the start of the data 
       strRequest = strRequest.substring(intPos + 1); 
      } else { 
    //Remove the method indicator 
       strRequest = strRequest.substring(HTTP_GET.length());     
      } 
     } else if (strRequest.startsWith(HTTP_POST)) { 
    //Discard the headers and jump to the data 
      if ((intPos = strRequest.lastIndexOf(CRLF)) >= 0) { 
       strRequest = strRequest.substring(intPos + CRLF.length()); 
      } 
     } 
     if (strRequest.length() > 1) { 
    //Extract the parameters      
      objParams = new clsHTTPparameters(strRequest); 
     }    
     if (strRequest.startsWith("/") == true) { 
    //Look for the document reference 
      strRequest = strRequest.substring(1);    
      eType = eMsgTypes.SEND_DOC;    
     } 
     if (objParams != null) { 
    //Transfer the payload to the request 
      String strPayload = objParams.getValue(PAYLOAD); 

      if (strPayload != null) { 
       byte[] arybytPayload = Base64.decodeBase64(strPayload.getBytes()); 
       strRequest = new String(arybytPayload); 
       strAMID = objParams.getValue(AJAX_ID); 
       strHKey = objParams.getValue(HANDLER_KEY); 
      } 
     } 
     if (eType == eMsgTypes.UNKNOWN 
      && strRequest.startsWith("{") && strRequest.endsWith("}")) { 
    //The payload is JSON, is there a type parameter? 
      String strType = strGetJSONItem(strRequest, JSON_LBL_TYPE); 

      if (strType != null && strType.length() > 0) { 
    //Decode the type     
       eType = eMsgTypes.valueOf(strType.toUpperCase().trim()); 
    //What system is the message from? 
       String strIP = strGetJSONItem(strRequest, JSON_LBL_IP) 
         ,strMAC = strGetJSONItem(strRequest, JSON_LBL_MAC);     
       if (strIP != null && strIP.length() > 0 
       && strMAC != null && strMAC.length() > 0) { 
    //Is this system known in the cluster? 
        clsIPmon objSystem = objAddSysToCluster(strIP, strMAC); 

        if (objSystem != null) { 
    //Update the date/time stamp of the remote system       
         objSystem.touch();       
        } 
    //This is an internal cluster message, no response required 
        return; 
       }     
      } 
     }    
     String strContentType = null, strRespPayload = null; 
     OutputStream out = sck.getOutputStream(); 
     byte[] arybytResponse = null; 
     boolean blnShutdown = false; 
     out.write("HTTP/1.0 200\n".getBytes()); 

     switch(eType) { 
     case SEND_DOC: 
      if (strRequest.length() <= 1) { 
       strRequest = HTML_ROOT + DEFAULT_DOC; 
      } else { 
       strRequest = HTML_ROOT + strRequest; 
      } 
      logMsg("HTTP Request for: " + strRequest, true); 

      if (strRequest.toLowerCase().endsWith(".css") == true) { 
       strContentType = MIME_CSS; 
      } else if (strRequest.toLowerCase().endsWith(".gif") == true) { 
       strContentType = MIME_GIF; 
      } else if (strRequest.toLowerCase().endsWith(".jpg") == true) { 
       strContentType = MIME_JPG; 
      } else if (strRequest.toLowerCase().endsWith(".js") == true) { 
       strContentType = MIME_JS; 
      } else if (strRequest.toLowerCase().endsWith(".png") == true) { 
       strContentType = MIME_PNG; 
      } else if (strRequest.toLowerCase().endsWith(".html") == true 
        || strRequest.toLowerCase().endsWith(".htm") == true) { 
       strContentType = MIME_HTML; 
      } 
      File objFile = new File(strRequest); 

      if (objFile.exists() == true) { 
       FileInputStream objFIS = new FileInputStream(objFile); 

       if (objFIS != null) { 
        arybytResponse = new byte[(int)objFile.length()]; 

        if (objFIS.read(arybytResponse) == 0) { 
         arybytResponse = null; 
        } 
        objFIS.close(); 
       } 
      } 
      break; 
     case CHANNEL_STS: 
      strRespPayload = strChannelStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case CLUSTER_STS: 
      strRespPayload = strClusterStatus(); 
      strContentType = MIME_JSON; 
      break; 
     case MODULE_STS: 
      strRespPayload = strModuleStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case NETWORK_INF: 
      strRespPayload = strNetworkInfo(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case NODE_STS: 
      strRespPayload = strNodeStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case POLL_STS: 
      strRespPayload = strPollStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case SYS_STS: 
    //Issue system status    
      strRespPayload = strAppStatus(); 
      strContentType = MIME_JSON; 
      break;   
     case SHUTDOWN: 
    //Issue instruction to restart system 
      strRespPayload = "Shutdown in progress!"; 
      strContentType = MIME_PLAIN; 
    //Flag that shutdown has been requested    
      blnShutdown = true; 
      break; 
     default: 
     } 
     if (strRespPayload != null) { 
    //Convert response string to byte array    
      arybytResponse = strRespPayload.getBytes(); 
    System.out.println("[ " + strRespPayload.length() + " ]: " + strRespPayload);   //HACK   
     }   
     if (arybytResponse != null && arybytResponse.length > 0) { 
      if (strContentType == MIME_JSON) { 
       String strResponse = "{"; 

       if (strAMID != null) { 
    //Include the request AJAX Message ID in the response 
        if (strResponse.length() > 1) { 
         strResponse += ","; 
        } 
        strResponse += "\"" + AJAX_ID + "\":" + strAMID; 
       } 
       if (strHKey != null) { 
        if (strResponse.length() > 1) { 
         strResponse += ","; 
        } 
        strResponse += "\"" + HANDLER_KEY + "\":\"" + strHKey + "\""; 
       } 
       if (strResponse.length() > 1) { 
        strResponse += ","; 
       } 
       strResponse += "\"payload\":" + new String(arybytResponse) 
          + "}";     
       arybytResponse = strResponse.getBytes(); 
      } 
      String strHeaders = ""; 

      if (strContentType != null) { 
       strHeaders += "Content-type: " + strContentType + "\n";     
      } 
      strHeaders += "Content-length: " + arybytResponse.length + "\n" 
         + "Access-Control-Allow-Origin: *\n" 
         + "Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT\n" 
         + "Access-Control-Allow-Credentials: true\n" 
         + "Keep-Alive: timeout=2, max=100\n" 
         + "Cache-Control: no-cache\n" 
         + "Pragma: no-cache\n\n"; 
      out.write(strHeaders.getBytes()); 
      out.write(arybytResponse); 
      out.flush();     
     } 
     out.close(); 
     sck.close(); 

     if (blnShutdown == true) { 
      String strSystem = mobjLocalIP.strGetIP(); 

      if (strSystem.compareTo(mobjLocalIP.strGetIP()) != 0) { 
    //Specified system is not the local system, issue message to remote system. 
       broadcastMessage("{\"" + JSON_LBL_TYPE + "\":\"" + 
                eMsgTypes.SHUTDOWN + "\"" 
           + ",\"" + JSON_LBL_TIME + "\":\"" + 
              clsTimeMan.lngTimeNow() + "\"}");        
      } else { 
    //Shutdown addressed to local system      
       if (getOS().indexOf("linux") >= 0) { 
    //TO DO!!!     
       } else if (getOS().indexOf("win") >= 0) { 
        Runtime runtime = Runtime.getRuntime(); 
        runtime.exec("shutdown /r /c \"Shutdown request\" /t 0 /f"); 
        System.exit(EXITCODE_REQUESTED_SHUTDOWN); 
       }    
      } 
     } 
    } catch (Exception ex) {    
    } finally { 
     if (sck != null) { 
      try { 
       sck.close(); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 

我想實現的分塊響應,在本分塊響應不是由上面的代碼支持。

[編輯]我已經嘗試通過添加方法來實現分塊響應:

/** 
    * @param strData - The data to split into chunks 
    * @return A string array containing the chunks 
    */ 
public static String[] arystrChunkData(String strData) { 
    int intChunks = (strData.length()/CHUNK_THRESHOLD_BYTESIZE) + 1; 
    String[] arystrChunks = new String[intChunks]; 
    int intLength = strData.length(), intPos = 0; 

    for(int c=0; c<arystrChunks.length; c++) {    
     if (intPos < intLength) { 
    //Extract a chunk from the data   
      int intEnd = Math.min(intLength - 1, intPos + CHUNK_THRESHOLD_BYTESIZE); 
      arystrChunks[c] = strData.substring(intPos, intEnd); 
     } 
    //Advance data position to next chunk   
     intPos += CHUNK_THRESHOLD_BYTESIZE; 
    }  
    return arystrChunks; 
} 

修改後的processRequest現在看起來是這樣的:

 private void processRequest(Socket sck) { 
    try { 
     //AJAX Parameters 
     final String AJAX_ID   = "ajmid"; 
     //The 'Handler Key' used to decode response   
     final String HANDLER_KEY  = "hkey"; 
     //Message payload   
     final String PAYLOAD   = "payload"; 
     //Post input buffer size    
     final int REQUEST_BUFFER_SIZE = 4096; 
     //Double carriage return marks the end of the headers   
     final String CRLF    = "\r\n"; 

     BufferedReader in = new BufferedReader(new InputStreamReader(sck.getInputStream())); 
     String strAMID = null, strHKey = null, strRequest; 
     char[] chrBuffer = new char[REQUEST_BUFFER_SIZE]; 
     StringBuffer sbRequest = new StringBuffer(); 
     eMsgTypes eType = eMsgTypes.UNKNOWN; 
     clsHTTPparameters objParams = null; 
     int intPos, intCount;    
     //Extract the entire request, including headers   
     if ((intCount = in.read(chrBuffer)) == 0) { 
      throw new Exception("Cannot read request!"); 
     } 
     sbRequest.append(chrBuffer, 0, intCount);   
     strRequest = sbRequest.toString(); 
     //What method is being used by this request? 
     if (strRequest.startsWith(HTTP_GET)) { 
     //The request should end with a HTTP marker, remove this before trying to interpret the data 
      if (strRequest.indexOf(HTTP_MARKER) != -1) { 
       strRequest = strRequest.substring(0, strRequest.indexOf(HTTP_MARKER)).trim(); 
      }    
     //Look for a data marker 
      if ((intPos = strRequest.indexOf(HTTP_DATA_START)) >= 0) { 
     //Data is present in the query, skip to the start of the data 
       strRequest = strRequest.substring(intPos + 1); 
      } else { 
     //Remove the method indicator 
       strRequest = strRequest.substring(HTTP_GET.length());     
      } 
     } else if (strRequest.startsWith(HTTP_POST)) { 
     //Discard the headers and jump to the data 
      if ((intPos = strRequest.lastIndexOf(CRLF)) >= 0) { 
       strRequest = strRequest.substring(intPos + CRLF.length()); 
      } 
     } 
     if (strRequest.length() > 1) { 
     //Extract the parameters      
      objParams = new clsHTTPparameters(strRequest); 
     }    
     if (strRequest.startsWith("/") == true) { 
     //Look for the document reference 
      strRequest = strRequest.substring(1);    
      eType = eMsgTypes.SEND_DOC;    
     } 
     if (objParams != null) { 
     //Transfer the payload to the request 
      String strPayload = objParams.getValue(PAYLOAD); 

      if (strPayload != null) { 
       byte[] arybytPayload = Base64.decodeBase64(strPayload.getBytes()); 
       strRequest = new String(arybytPayload); 
       strAMID = objParams.getValue(AJAX_ID); 
       strHKey = objParams.getValue(HANDLER_KEY); 
      } 
     } 
     if (eType == eMsgTypes.UNKNOWN 
      && strRequest.startsWith("{") && strRequest.endsWith("}")) { 
     //The payload is JSON, is there a type parameter? 
      String strType = strGetJSONItem(strRequest, JSON_LBL_TYPE); 

       if (strType != null && strType.length() > 0) { 
     //Decode the type     
       eType = eMsgTypes.valueOf(strType.toUpperCase().trim()); 
     //What system is the message from? 
       String strIP = strGetJSONItem(strRequest, JSON_LBL_IP) 
         ,strMAC = strGetJSONItem(strRequest, JSON_LBL_MAC);     
       if (strIP != null && strIP.length() > 0 
       && strMAC != null && strMAC.length() > 0) { 
     //Is this system known in the cluster? 
        clsIPmon objSystem = objAddSysToCluster(strIP, strMAC); 

        if (objSystem != null) { 
     //Update the date/time stamp of the remote system       
         objSystem.touch();       
        } 
     //This is an internal cluster message, no response required 
        return; 
       }     
      } 
     }    
     String strContentType = null, strRespPayload = null;    
     OutputStream out = sck.getOutputStream(); 
     byte[] arybytResponse = null; 
     boolean blnShutdown = false; 
     //Start the writing the headers 
     String strHeaders = "HTTP/1.0 200\n" 
          + "Date: " + (new Date()).toString() + "\n" 
          + "Access-Control-Allow-Origin: *\n" 
          + "Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE, PUT\n" 
          + "Access-Control-Allow-Credentials: true\n" 
          + "Keep-Alive: timeout=2, max=100\n" 
          + "Cache-Control: no-cache\n" 
          + "Pragma: no-cache\n";    
     out.write(strHeaders.getBytes()); 
     strHeaders = ""; 

     switch(eType) { 
     case SEND_DOC: 
      if (strRequest.length() <= 1) { 
       strRequest = HTML_ROOT + DEFAULT_DOC; 
      } else { 
       strRequest = HTML_ROOT + strRequest; 
      } 
      logMsg("HTTP Request for: " + strRequest, true); 

      if (strRequest.toLowerCase().endsWith(".css") == true) { 
       strContentType = MIME_CSS; 
      } else if (strRequest.toLowerCase().endsWith(".gif") == true) { 
       strContentType = MIME_GIF; 
      } else if (strRequest.toLowerCase().endsWith(".jpg") == true) { 
       strContentType = MIME_JPG; 
      } else if (strRequest.toLowerCase().endsWith(".js") == true) { 
       strContentType = MIME_JS; 
      } else if (strRequest.toLowerCase().endsWith(".png") == true) { 
       strContentType = MIME_PNG; 
      } else if (strRequest.toLowerCase().endsWith(".html") == true 
        || strRequest.toLowerCase().endsWith(".htm") == true) { 
       strContentType = MIME_HTML; 
      } 
      File objFile = new File(strRequest); 

      if (objFile.exists() == true) { 
       FileInputStream objFIS = new FileInputStream(objFile); 

       if (objFIS != null) { 
        arybytResponse = new byte[(int)objFile.length()]; 

        if (objFIS.read(arybytResponse) == 0) { 
         arybytResponse = null; 
        } 
        objFIS.close(); 
       } 
      } 
      break; 
     case CHANNEL_STS: 
      strRespPayload = strChannelStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case CLUSTER_STS: 
      strRespPayload = strClusterStatus(); 
      strContentType = MIME_JSON; 
      break; 
     case MODULE_STS: 
      strRespPayload = strModuleStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case NETWORK_INF: 
      strRespPayload = strNetworkInfo(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case NODE_STS: 
      strRespPayload = strNodeStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case POLL_STS: 
      strRespPayload = strPollStatus(strRequest); 
      strContentType = MIME_JSON; 
      break; 
     case SYS_STS: 
     //Issue system status    
      strRespPayload = strAppStatus(); 
      strContentType = MIME_JSON; 
      break;   
     case SHUTDOWN: 
     //Issue instruction to restart system 
      strRespPayload = "Shutdown in progress!"; 
      strContentType = MIME_PLAIN; 
     //Flag that shutdown has been requested    
      blnShutdown = true; 
      break; 
     default: 
     } 
     if (strRespPayload != null) { 
     //Convert response string to byte array    
      arybytResponse = strRespPayload.getBytes(); 
     }   
     if (arybytResponse != null && arybytResponse.length > 0) { 
      boolean blnChunked = false; 

      if (strContentType != null) { 
       strHeaders += "Content-type: " + strContentType + "\n";     
      }    
      if (strContentType == MIME_JSON) { 
       String strResponse = "{"; 

       if (strAMID != null) { 
     //Include the request AJAX Message ID in the response 
        if (strResponse.length() > 1) { 
         strResponse += ","; 
        } 
        strResponse += "\"" + AJAX_ID + "\":" + strAMID; 
       } 
       if (strHKey != null) { 
        if (strResponse.length() > 1) { 
         strResponse += ","; 
        } 
        strResponse += "\"" + HANDLER_KEY + "\":\"" + strHKey + "\""; 
       } 
       if (strResponse.length() > 1) { 
        strResponse += ","; 
       } 
       strResponse += "\"payload\":" + new String(arybytResponse) 
          + "}"; 
     //How big is the response? 
    if (strResponse.length() > CHUNK_THRESHOLD_BYTESIZE) { 
        blnChunked = true; 
        strHeaders += "Transfer-Encoding: chunked\n\n"; 
        out.write(strHeaders.getBytes()); 
     //Slice up the string into chunks 
          String[] arystrChunks = arystrChunkData(strResponse); 

        for(int c=0; c<arystrChunks.length; c++) { 
         String strChunk = arystrChunks[c]; 

         if (strChunk != null) { 
          String strLength = Integer.toHexString(strChunk.length()) + "\r\n"; 
          strChunk += "\r\n"; 
          out.write(strLength.getBytes()); 
          out.write(strChunk.getBytes()); 
         }       
        } 
     //Last chunk is always 0 bytes      
        out.write("0\r\n\r\n".getBytes()); 
       } else { 
        arybytResponse = strResponse.getBytes(); 
       } 
      } 
      if (blnChunked == false) {  
       strHeaders += "Content-length: " + arybytResponse.length + "\n\n";       
       out.write(strHeaders.getBytes()); 
       out.write(arybytResponse); 
      } 
      out.flush();     
     } 
     out.close(); 
     sck.close(); 

     if (blnShutdown == true) { 
      String strSystem = mobjLocalIP.strGetIP(); 

      if (strSystem.compareTo(mobjLocalIP.strGetIP()) != 0) { 
     //Specified system is not the local system, issue message to remote system. 
       broadcastMessage("{\"" + JSON_LBL_TYPE + "\":\"" + 
                eMsgTypes.SHUTDOWN + "\"" 
           + ",\"" + JSON_LBL_TIME + "\":\"" + 
              clsTimeMan.lngTimeNow() + "\"}");        
      } else { 
    //Shutdown addressed to local system      
       if (getOS().indexOf("linux") >= 0) { 
     //TO DO!!!     
       } else if (getOS().indexOf("win") >= 0) { 
        Runtime runtime = Runtime.getRuntime(); 
        runtime.exec("shutdown /r /c \"Shutdown request\" /t 0 /f"); 
        System.exit(EXITCODE_REQUESTED_SHUTDOWN); 
       }    
      } 
     } 
    } catch (Exception ex) {    
    } finally { 
     if (sck != null) { 
      try { 
       sck.close(); 
      } catch (IOException ex) { 
       ex.printStackTrace(); 
      } 
     } 
    } 
} 

我讀過一些規範分塊的迴應,以及據我所知我正在以正確的格式發送數據,但是我沒有收到瀏覽器中的任何內容。

我可能錯誤地認爲瀏覽器會正確拼接成一個塊,但我可能是錯的。客戶端處理程序如下所示:

 this.responseHandler = function() { 
try {  
    if (mobjHTTP == null 
    || !(mobjHTTP.readyState == 4 && mobjHTTP.status == 200) 
    || !(mstrResponseText = mobjHTTP.responseText) 
    || mstrResponseText.length == 0) { 
    //Not ready or no response to decode  
    return; 
    } 
    //Do something with the response 
    } catch(ex) { 
    T.error("responseHandler:", ex); 
} 

};

該處理器是建立在其他地方的對象:

mobjHTTP.onreadystatechange = this.responseHandler; 
+0

爲什麼你需要一個分塊響應? TCP已經做到了這一點 –

+0

我創建了一個JSON響應,它可以相當大> 4K。一些瀏覽器如IE會容忍更大的數據包。我想確保解決方案對所有人都有效,方法是將每個數據塊的最大數據包大小保持爲768字節。 – SPlatten

+0

我很確定你在任何流行的瀏覽器中都沒有問題,GET url的長度有限制,但是對響應呢?你確定你有問題嗎? –

回答

1

解決了,不知道爲什麼,但除去頭:

Transfer-Encoding: chunked 

而且也塊,在每個月初長度chunk解決了這個問題,我仍然以768字節塊寫入數據。這工作可靠,非常好。不知道爲什麼我不得不這樣做。

public static String[] arystrChunkData(String strData) { 
      int intChunks = (strData.length()/CHUNK_THRESHOLD_BYTESIZE) + 1; 
      String[] arystrChunks = new String[intChunks]; 
      int intLength = strData.length(), intPos = 0; 

      for(int c=0; c<arystrChunks.length; c++) {    
       if (intPos < intLength) { 
    //Extract a chunk from the data   
        int intEnd = Math.min(intLength, intPos + CHUNK_THRESHOLD_BYTESIZE); 
        arystrChunks[c] = strData.substring(intPos, intEnd); 
        intPos = intEnd; 
       } 
      }  
      return arystrChunks; 
     } 

循環寫入塊,在開始時沒有長度和在所述塊的端部沒有0字節需要:

String[] arystrChunks = arystrChunkData(strResponse); 
    for(String strChunk : arystrChunks) { 
      if (strChunk != null) { 
        out.write(strChunk.getBytes()); 
      }       
    } 
+0

您正在以768字節的塊形式將數據寫入輸出流。不過,我認爲每個大塊後都沒有潮水。通過不發送'Transfer-Encoding:chunked'頭並且不在每個塊之前發送塊長度;實際上,當輸出流最終被刷新時,您將在一個響應中發送完整數據。寫完每個塊後,你不應該刷新輸出流嗎? –

1

作爲

以產生從數據串塊的最終方法我已經評論過,HTTP響應大小沒有官方限制。 TCP爲您完成這項工作。但是,您始終可以通過爲現代瀏覽器設置Content-Length :: 32位整數最大大小或64位來配置Web服務器以實施此類策略(請參閱here)。

從技術上講,您可以使用分塊傳輸進行無限制的回覆,就像您在帖子中陳述的一樣。理論上,這用於繞過最大內容長度。

大多數情況下,如果需要巨大的JSON文件(至少有一些MB大小),可以通過順序AJAX請求使用某種分頁邏輯。在你的情況下,你可以將你的大JSON數據以編程方式分割爲塊,並通過另一個AJAX請求發送每個塊。然後,讓Javascript執行合併任務。

通常,某個MB大小的JSON響應將在任何瀏覽器上成功加載。我建議你看看this的文章;它已經3歲了,但我想現在情況會更好。

簡而言之,上述基準指出,尺寸小於35 MB的JSON可能會在任何現代桌面瀏覽器上成功加載。但是,這對移動瀏覽器來說可能並非如此。例如,有一些reports移動Safari瀏覽器對> 10MB Json文件的限制。