2012-03-13 71 views
0

總之,我有一個Servlet,它檢索圖片/視頻e t.c.來自底層數據存儲。爲ServletResponce指定InputStream,而不是在OutputStream中複製InputStream

爲了歸檔此我需要將文件的InputStream複製到ServletResponce * 的OutputStream *

從我的角度來看,這不是有效的,因爲我需要複製的文件內存發送之前,指定InputStream會更方便,在讀取緩衝區中的數據後,OutputStream會讀取數據並立即發送。

我看着ServletResponce文檔,它有一些緩衝區的消息數據,所以我有幾個關於它的問題。

這是正確的機制嗎? 如果我決定在Servlet處理結束時不發送文件? 例如: 如果我抄的InputStream的OutputStream,然後發現,這不是授權請求,用戶無權查看該對象(錯誤在設計也許)我仍然會發送一些數據客戶,儘管這不是我想要的,或者不是。

回答

0

這是正確的機制嗎?

基本上,它是由Servlet APIs提供的機構。考慮到這一點,您需要設計您的servlet。

(這是很難看到它可能做任何其他方式。一個read系統調用從設備(磁盤)讀取數據到內存中。一個write系統調用從內存到一個設備中寫入數據(網絡接口)。沒有系統調用可以直接將數據從一個設備傳輸到另一個設備,最好的辦法是減少應用程序中的數據複製量如果您使用類似IOUtils.copy的東西,可以避免通過應用程序memort的唯一方法是使用針對內容傳輸優化的一些專用硬件/操作系統組合。)

但是,這可能是無論如何。在大多數情況下,性能瓶頸可能是數據在網絡上的移動。數據可能會從磁盤讀取到內存,複製並寫入網絡接口的速度要比通過網絡傳輸到用戶的Web瀏覽器(或其他)快幾個數量級。

如果它不是沒有爭議,那麼一個實際的內容交付方式是使用一個單獨的web服務器在本地代碼中實現,我們優化以提供靜態內容;例如類似nginx。)

如果我決定不在Servlet處理結束時發送文件?例如:如果我已將InputStream複製到OutputStream中,然後發現這不是授權請求,並且用戶無權查看此對象(可能是設計錯誤),但我仍然會向客戶端發送一些數據,雖然這是不是我想要的,或者不是。

你應該編寫你的servlet來進行訪問檢查,然後再將內容讀入內存。理想情況下,在通過發送響應頭「提交」響應之前。

1

爲了解決您的第一關注,你可以輕鬆地複製到InputStream使用OutputStreamIOUtils阿帕奇百科全書郎鹹平:

IOUtils.copy(fileInputStream, servletOutputStream); 

它採用4K緩衝,所以內存的消耗不應該是一個問題。事實上,你不能直接發送來自InputStream的數據。在最低級別,操作系統仍然需要將文件內容讀取到某個內存位置,並且爲了將其發送到套接字,您需要提供要發送數據的內存位置。流只是一個有用的抽象。

關於第二個問題:這就是HTTP的工作原理:如果您開始將數據流傳輸到客戶端,那麼servlet容器會首先發送所有響應標頭。如果在中間中止,從客戶端角度看,它看起來像中斷的下載。

+0

我正好利用IOUtils.copy爲我處理已經:) 最關心的是第二個問題 - 這是從我的角度來看,流動,因爲我不想送任何東西,直到Servlet的處理已經結束,這可能容易出錯。 4K緩衝區是IOUtils緩衝區的默認大小,因此使用另一個用於Servlet處理的緩衝區將不會有效。 如果我想發送8K數據報,我要麼需要使用IOUtils讀取兩次,要麼添加可配置的複製實現。 – mavarazy 2012-03-13 14:04:03

相關問題