2013-04-05 37 views
2

我試圖圍繞Netty 4實現一個HTTP服務器,當總數據大小未知時使用分塊傳輸編碼來服務HttpResponses主體。作爲一個起點,我只是簡單地將HttpStaticFileServerHandler(在https://github.com/netty/netty/tree/netty-4.0.0.CR1/example/src/main/java/io/netty/example/http/file中找到)改爲使用ChunkedStream而不是ChunkedFile(它們都是ChunkedByteInputs)。更改Netty 4 HTTP文件服務器示例以使用ChunkedStream而不是ChunkedFile

據我所知,它在原始示例用例中使用FileInputStream並不理想,但我認爲它是重用已知代碼的一個好例子。

所以,這裏距離io.netty.example.http.file包(與4.0.0.CR1)對HttpStaticFileServerHandler類DIFF:

diff --git a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java 
index 904579b..0d3592f 100644 
--- a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java 
+++ b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java 
@@ -27,13 +27,14 @@ import io.netty.handler.codec.http.FullHttpResponse; 
import io.netty.handler.codec.http.HttpHeaders; 
import io.netty.handler.codec.http.HttpResponse; 
import io.netty.handler.codec.http.HttpResponseStatus; 
-import io.netty.handler.stream.ChunkedFile; 
+import io.netty.handler.stream.ChunkedStream; 
import io.netty.util.CharsetUtil; 

import javax.activation.MimetypesFileTypeMap; 
import java.io.File; 
+import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
-import java.io.RandomAccessFile; 
+import java.io.InputStream; 
import java.io.UnsupportedEncodingException; 
import java.net.URLDecoder; 
import java.text.SimpleDateFormat; 
@@ -159,17 +160,15 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda 
      } 
     } 

-  RandomAccessFile raf; 
+  InputStream raf; // Use an InputStream instead of a RandomAccessFile 
     try { 
-   raf = new RandomAccessFile(file, "r"); 
+   raf = new FileInputStream(file); 
     } catch (FileNotFoundException fnfe) { 
      sendError(ctx, NOT_FOUND); 
      return; 
     } 
-  long fileLength = raf.length(); 

     HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK); 
-  setContentLength(response, fileLength); 
     setContentTypeHeader(response, file); 
     setDateAndCacheHeaders(response, file); 
     if (isKeepAlive(request)) { 
@@ -180,7 +179,7 @@ public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAda 
     ctx.write(response); 

     // Write the content. 
-  ChannelFuture writeFuture = ctx.write(new ChunkedFile(raf, 0, fileLength, 8192)); 
+  ChannelFuture writeFuture = ctx.write(new ChunkedStream(raf)); // Use a ChunkedStream instead of a ChunkedFile 

     // Decide whether to close the connection or not. 
     if (!isKeepAlive(request)) { 

這裏完整的更改的文件: https://gist.github.com/eskatos/5311587

更改最小化:使用FileInputStream而不是使用RandomAccessFile和ChunkedStream而不是ChunkedFile。管道未觸及。

要重現,只需將更改應用到Netty示例,運行它並嘗試下載任何文件。

在此更改之後,目錄列表顯然起作用,因爲響應沒有被分塊,但文件下載沒有。客戶端下載文件,但永遠不會完成下載,保持連接並永遠等待。我已經嘗試了幾個來自瀏覽器的curl,wget等等。我還試圖在管道中添加一個ByteLoggingHandler,並且我可以看到一個空的尾部塊,所以我不明白瀏覽器爲什麼仍在等待數據。

任何線索?

回答

1

爲了終止未知尺寸的分塊傳輸(Content-Length未知,因此未指定),您只需發送一個空塊最後一塊。這允許保持連接打開以支持持久連接:

 ctx.write(new ChunkedInputAdapter(new ChunkedStream(raf, 8192))); 
     ChannelFuture writeFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT); 

下面是一個完整的例子: https://github.com/scireum/sirius/blob/develop/web/src/sirius/web/http/Response.java#L649

+0

我們最近添加了一個'ChunkedInput'實現專用於此:https:// github。com/netty/netty/blob/master/codec -http/src/main/java/io/netty/handler/codec/http/HttpChunkedInput.java – trustin 2014-01-19 13:38:18

+0

很好看:正如我剛纔所做的那樣,內容壓縮問題:http://andreas.haufler.info/2014/01/making-http-content-compression-work-in.html。也許你們也可以改進HttpContentCompressor(不壓縮JPEG,ZIP等或小文件......)我會很樂意提供一個請求... – 2014-01-21 21:25:44

+0

當然!讓我期待您的拉動請求/功能建議等。 – trustin 2014-01-22 06:29:19

1

如果您沒有指定Content-Length標頭,則客戶端不知道您正在發送的內容的長度,因此它會等到服務器關閉連接,並且收到的所有內容直到將斷開連接視爲內容爲止。

因此,您必須執行下列操作之一:

  1. 添加Content-Length
  2. 關閉發送內容
  3. 後的連接採用分塊編碼與Transfer-Encoding: chunked
發送內容
+0

HTTP 1.1允許那裏沒有Content-Length頭和使用分塊編碼的。 http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 – 2013-12-04 16:48:54

+0

@MikePone:我想你一定誤解了信任的答案。您的評論可以改爲「HTTP 1.1允許您的選項#3」,這是事實,但有點奇怪。 – ruakh 2016-08-20 21:05:14

相關問題