2011-06-28 35 views
0

我正在處理一些代碼,這些代碼經常通過HTTP將大型數據包POST到IIS上的REST服務器。我正在使用RIM/JavaME HTTPConnection類。黑莓Java - 通過HTTP連接固定長度流式POST正文

據我所知,HTTPConnection使用內部緩衝區在將整個內容發送到服務器之前「收集」輸出流。我並不感到驚訝,因爲這也是默認情況下HttpURLConnect的工作方式。 (我認爲這樣做是爲了正確設置內容長度。)但是在JavaSE中,我可以通過使用方法setFixedLengthStreamingMode覆蓋此行爲,這樣當我在輸出流上調用flush時,它會發送流的「塊」 。在手機上,這種額外的緩衝在內存方面太昂貴了。

在Blackberry中當你知道提前的內容長度時,Java有沒有一種方法可以對HTTP請求進行固定長度的流式傳輸?

回答

0

所以,我從來沒有找到一種方法來做到這一點是HTTPConnection的基礎API。相反,我創建了一個套接字並用我自己的簡單HTTPClient包裝它,它支持分塊。

下面是我在BB7.0上使用和測試的原型。

package mypackage; 

import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import javax.microedition.io.Connector; 
import javax.microedition.io.SocketConnection; 

public class MySimpleHTTPClient{ 

    SocketConnection sc; 
    String HttpHeader; 
    OutputStreamWriter outWriter; 
    InputStreamReader inReader; 

    public void init(
      String Host, 
      String port, 
      String path, 
      int ContentLength, 
      String ContentType) throws IllegalArgumentException, IOException 
    { 
     String _host = (new StringBuffer()) 
        .append("socket://") 
        .append(Host) 
        .append(":") 
        .append(port).toString(); 
     sc = (SocketConnection)Connector.open(_host); 
     sc.setSocketOption(SocketConnection.LINGER, 5); 
     StringBuffer _header = new StringBuffer(); 
     //Setup the HTTP Header. 
     _header.append("POST ").append(path).append(" HTTP/1.1\r\n"); 
     _header.append("Host: ").append(Host).append("\r\n"); 
     _header.append("Content-Length: ").append(ContentLength).append("\r\n"); 
     _header.append("Content-Type: ").append(ContentType).append("\r\n"); 
     _header.append("Connection: Close\r\n\r\n"); 
     HttpHeader = _header.toString(); 
    } 

    public void openOutputStream() throws IOException{ 
     if(outWriter != null) 
      return; 
     outWriter = new OutputStreamWriter(sc.openOutputStream()); 
     outWriter.write(HttpHeader, 0 , HttpHeader.length()); 
    } 

    public void openInputStream() throws IOException{ 
     if(inReader != null) 
      return; 
     inReader = new InputStreamReader(sc.openDataInputStream()); 
    } 

    public void writeChunkToServer(String Chunk) throws Exception{ 
     if(outWriter == null){ 
      try { 
       openOutputStream(); 
      } catch (IOException e) {e.printStackTrace();} 
     } 
     outWriter.write(Chunk, 0, Chunk.length()); 
    } 

    public String readFromServer() throws IOException { 
     if(inReader == null){ 
      try { 
       openInputStream(); 
      } catch (IOException e) {e.printStackTrace();} 
     } 
     StringBuffer sb = new StringBuffer(); 
     int data = inReader.read(); 
     //Note :: This will also read the HTTP headers.. 
     // If you need to parse the headers, tokenize on \r\n for each 
     // header, the header section is done when you see \r\n\r\n 
     while(data != -1){ 
      sb.append((char)data ); 
      data = inReader.read(); 
     } 
     return sb.toString(); 
    } 

    public void close(){ 
     if(outWriter != null){ 
      try { 
       outWriter.close(); 
      } catch (IOException e) {} 
     } 
     if(inReader != null){ 
      try { 
       inReader.close(); 
      } catch (IOException e) {} 
     } 
     if(sc != null){ 
      try { 
       sc.close(); 
      } catch (IOException e) {} 
     } 
    } 
} 

下面是它例如使用:

MySimpleHTTPClient myConn = new MySimpleHTTPClient() ; 
String chunk1 = "ID=foo&data1=1234567890&chunk1=0|"; 
String chunk2 = "ID=foo2&data2=123444344&chunk1=1"; 
try { 
    myConn.init(
      "pdxsniffe02.webtrends.corp", 
      "80", 
      "TableAdd/234234234443?debug=1", 
      chunk1.length() + chunk2.length(), 
      "application/x-www-form-urlencoded" 
    ); 

    myConn.writeChunkToServer(chunk1); 
    //The frist chunk is already on it's way. 
    myConn.writeChunkToServer(chunk2); 
    System.out.println(myConn.readFromServer()); 

} catch (IllegalArgumentException e) { 
    e.printStackTrace(); 
} catch (IOException e) { 
    e.printStackTrace(); 
} catch (Exception e) { 
    e.printStackTrace(); 
}finally{ 
    myConn.close(); 
}