2011-09-16 70 views
6

臨時解決:InputStream closed in Apache FileUpload API如何閱讀內容處置標題的內容?


我想讀的內容部署頭的內容,但request.getHeader ("content-disposition")總是返回null,request.getHeader ("content-type")只返回第一線,像這樣multipart/form-data; boundary=AaB03x

Supose我收到以下標題:

Content-Type: multipart/form-data; boundary=AaB03x 

--AaB03x 
Content-Disposition: form-data; name="submit-name" 

Larry 
--AaB03x 
Content-Disposition: form-data; name="files"; filename="file1.txt" 
Content-Type: text/plain 

... contents of file1.txt ... 
--AaB03x-- 

我想讀的所有內容處置頭。怎麼樣?

謝謝。


EDIT1:我真的想解決的問題是當客戶端發送超過最大尺寸,因爲當你調用request.getPart(「東西」),它不管什麼部分文件名稱,因爲即使請求不包含此參數名稱,它總是會拋出IllegalStateException異常。

例子:

Part part = request.getPart ("param"); 
String value = getValue (part); 
if (value.equals ("1")){ 
    doSomethingWithFile1 (request.getPart ("file1")) 
}else if (value.equals (2)){ 
    doSomethingWithFile2 (request.getPart ("file2")) 
} 

private String getValue (Part part) throws IOException{ 
    if (part == null) return null; 

    BufferedReader in = null; 
    try{ 
     in = new BufferedReader (new InputStreamReader (part.getInputStream(), request.getCharacterEncoding())); 
    }catch (UnsupportedEncodingException e){} 

    StringBuilder value = new StringBuilder(); 
    char[] buffer = new char[1024]; 
    for (int bytesRead; (bytesRead = in.read (buffer)) != -1;) { 
     value.append (buffer, 0, bytesRead); 
    } 

    return value.toString(); 
} 

我不能這樣做,因爲如果客戶端發送一個超過最大尺寸getPart第一個電話會拋出異常(見getPart() Javadoc)的文件,所以我不能知道我收到了哪個文件。

這就是爲什麼我要閱讀內容處置標題。我想讀取參數「param」來知道哪個文件拋出異常。


EDIT2:嗯,與發佈Servlet 3.0規範,因爲如果一個文件拋出一個異常,則無法讀取該文件字段名,你無法控制前一種情況的API。這是使用包裝的負面部分,因爲很多功能消失了......也可以使用FileUpload動態設置MultipartConfig註釋。

如果文件超過最大文件大小,api會拋出FileSizeLimitExceededException異常。該例外提供了兩種獲取字段名稱和文件名的方法。

但是!!我的問題仍然沒有解決,因爲我想讀取與同一形式的文件一起發送的另一個參數的值。( 「參數」 的前面例子中的值)


EDIT3:我正在此。只要我寫代碼,我會在這裏發佈!

+0

不是重複。 –

回答

5

request.getHeader ("content-disposition")將在您的情況下返回null,因爲Content-Disposition標題出現在HTTP POST主體中,因此要求它們分開處理。實際上,Content-Disposition只是一個有效的HTTP響應頭。作爲請求的一部分,它永遠不會被視爲標題。

您最好使用文件上傳庫(如Commons FileUpload)或Servlet Spec 3.0的內置文件上傳功能來讀取Content-Disposition標頭(間接)。實現Servlet Spec 3.0所需的文件上傳功能所需的Java EE 6容器通常在底層使用Apache Commons FileUpload。

如果您因爲某些正當理由而忽略這些庫,而是自己閱讀頭文件,那麼我建議您查看類的Apache Commons FileUpload的parseHeaderLinegetParsedHeaders方法。請注意,這些方法實際上是從與HttpServletRequest關聯的InputStream中讀取的,並且無法兩次讀取該流。如果您想首先閱讀代碼中的Content-Disposition標頭,然後使用Apache Commons FileUpload解析請求,則必須通過ServletRequestWrapper,如果將原始請求發送到FileUpload API,它將包裝一個副本。反向序列還要求您創建原始請求的副本,並傳遞包含此副本的ServletRequestWrapper到FileUpload API。總體而言,這是糟糕的設計,因爲在內存(或磁盤)上覆制整個流只是爲了讀取請求主體兩次是沒有意義的。

+0

我已經用完整的解釋編輯了這個問題。 –

1

嘗試使用part.getName()

這裏是一個樣本。

HTML文件:

<form action="UploadServlet" method="post" enctype="multipart/form-data"> 
    <input type="text" value="phu" name="info"> 
    <input type="file" name="file1"/> <input type="submit"/> 
</form> 

的Servlet:

String field; 

for (Part part : request.getParts()) { 
    field = part.getName(); 
    if (field.equals("info")) { 
     // Your code here 
    } else if (field.equals("file1")) { 
     // Your code here 
    } 
} 
+0

警告:這隻適用於符合Servlet 3.0規範的容器(例如,不是某些版本的嵌入式Jetty)。 –