2015-09-16 73 views
0

我想創建一個使用Java NIO的HTTP靜態文件服務器,它適用於小文件,但似乎會截斷較大文件的HTTP響應(3.8 MB圖像中有672 KB根據我的Chrome Inspector返回,並且我的瀏覽器顯示部分損壞的圖像)。這段代碼是否錯誤?NIO Http文件服務器 - 連接過早關閉

(我知道這是你現有的庫,最終我將使用一個在我的項目,但最初我想實現一個基本的自己,看看我的項目的概念是可行的。)

Iterator<SelectionKey> keys = selector.selectedKeys().iterator(); 
while (keys.hasNext()) { 
    SelectionKey key = keys.next(); 
    keys.remove(); 
    if (key.isAcceptable()) { 
     // New Client encountered 
     serverSocket.accept().configureBlocking(false) 
       .register(selector, SelectionKey.OP_READ); 

    } else if (key.isReadable()) { 
     // Additional data for existing client encountered 
     SocketChannel selectedClient = (SocketChannel) key.channel(); 
     ByteBuffer buffer = ByteBuffer.allocate(548); 
     String requestedFile2 = getRequstedFile(key, selectedClient, buffer); 
     buffer.clear(); 
     buffer.flip(); 

     FileChannel fc = FileChannel.open(Paths.get(requestedFile2)); 
     String string = "HTTP/1.1 200 Ok\nContent-Type: image/jpeg\nContent-Length: " 
       + (Files.size(Paths.get(requestedFile2)) + "\n\n"); 
     selectedClient.write(ByteBuffer.wrap(string.getBytes())); 
     while (fc.read(buffer) > -1) { 
      buffer.flip(); // read from the buffer 
      selectedClient.write(buffer); 
      buffer.clear(); 
     } 
     selectedClient.close(); 

    } 
} 

(異常處理等爲簡潔起見省略)

EDIT

我有一個內容長度失配錯誤消息。那麼,使用NIO API讀取文件內容時,確定HTTP響應大小的正確方法是什麼?

回答

1
buffer.clear(); 

這應該是

buffer.compact(); 

和循環應該是

while (fc.read(buffer) > 0 || buffer.position() > 0) 

你承擔一切得到了由寫書面。

此外,您還需要將HTTP標題行結束符更改爲\r\n

而你需要研究有關內容長度的RFC 2616。

+0

我做了3個編輯,但現在瀏覽器不顯示任何內容。另外,我不確定「將數據複製到文件」的含義。我正在嘗試讀取文件。我們在談論同樣的問題嗎? –

1

我想你必須檢查從selectedClient.write()的返回值,檢查SocketChannel.write()文檔:
除非另有規定,一個寫操作只會寫所有的R請求的字節後返回。某些類型的通道,根據其狀態,可能只寫入一些字節或可能根本沒有。

這可能是這種情況。可以添加另一個內部循環,只要緩衝區中剩餘字節,它就會寫入輸出。或者你也可以根據例如ByteBuffer.compact()修改循環:http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html#compact()

while (buffer.position() > 0 || fc.read(buffer) > 0) { 
     buffer.flip(); // read from the buffer 
     selectedClient.write(buffer); 
     buffer.compact(); 
} 

請記住,該代碼假設是selectedClient阻止。如果不是這種情況,您需要調用另一個select(),等待selectedClient變爲可寫...