Как я могу прочитать содержимое заголовка content-disposition?

ВРЕМЕННО РЕШЕНО: InputStream закрыт в Apache FileUpload API


Я хочу прочитать содержимое заголовка content-disposition, но request.getHeader ("content-disposition") всегда возвращает null, а request.getHeader ("content-type") возвращает только первую строку, например multipart/form-data; boundary=AaB03x.

Предположим, я получаю следующий заголовок:

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: Ну, с API, который публикует спецификацию Servlet 3.0, вы не можете контролировать предыдущий случай, потому что, если файл вызывает исключение, вы не можете прочитать имя поля файла. Это отрицательная сторона использования оболочки, потому что многие функции исчезают... Также с помощью FileUpload вы можете динамически устанавливать аннотацию MultipartConfig.

Если файл превышает максимальный размер файла, API выдает Исключение FileSizeLimitExceededException. Исключение предоставляет 2 метода для получения имени поля и имени файла.

Но!! моя проблема все еще не решена, потому что я хочу прочитать значение другого параметра, отправленного вместе с файлом в той же форме. (значение "param" в предыдущем пример)


EDIT3: я работаю над этим. Как только я напишу код, я опубликую его здесь!


person Gabriel Llamas    schedule 16.09.2011    source источник


Ответы (2)


request.getHeader ("content-disposition") вернет null в вашем случае, так как заголовки Content-Disposition появляются в теле HTTP POST, что требует их отдельной обработки. На самом деле Content-Disposition — это всего лишь допустимый заголовок HTTP-ответа. Как часть запроса, он никогда не будет рассматриваться как заголовок.

Вам лучше использовать библиотеку загрузки файлов, такую ​​как Commons FileUpload, или встроенные функции загрузки файлов Servlet Spec 3.0 для чтения заголовка Content-Disposition (косвенно). Контейнеры Java EE 6, необходимые для реализации функций загрузки файлов, требуемых Servlet Spec 3.0, часто используют под капотом Apache Commons FileUpload.

Если вы хотите игнорировать эти библиотеки по какой-то уважительной причине и вместо этого сами читать заголовки, я бы рекомендовал посмотреть методы parseHeaderLine и getParsedHeaders в FileUploadBase класса Apache Commons FileUpload. Обратите внимание, что эти методы фактически читают из InputStream, связанного с HttpServletRequest, и вы не можете прочитать поток дважды. Если вы хотите сначала прочитать заголовок Content-Disposition в своем коде, а затем использовать Apache Commons FileUpload для анализа запроса, вам придется передать ServletRequestWrapper, который упаковывает копию исходного запроса в API FileUpload. Обратная последовательность также требует, чтобы вы создали копию исходного запроса и передали ServletRequestWrapper обертку этой копии в API FileUpload. В целом, это плохой дизайн, так как нет смысла копировать весь поток в памяти (или на диске) только для того, чтобы дважды прочитать тело запроса.

person Vineet Reynolds    schedule 16.09.2011

Попробуйте использовать 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>

Сервлет:

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
    }
}
person Phu Khong    schedule 20.07.2012
comment
Предостережение: это работает только для контейнера, совместимого со спецификацией Servlet 3.0 (например, не для некоторых версий встроенного Jetty). - person Darrell Teague; 20.05.2016