barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)
Показаны сообщения с ярлыком multipart/form-data. Показать все сообщения
Показаны сообщения с ярлыком multipart/form-data. Показать все сообщения

четверг, 19 апреля 2012 г.

Проблема с бьющейся кодировкой имен загружаемых на сервер файлов при использовании org.apache.commons.fileupload

Проблема:

При обработке загружаемых на сервер файлов с помощью org.apache.commons.fileupload бьется кодировка имен файлов, получаемых вызовом FileItem.getName(). Заголовки запроса кодируются UTF8.

Причина:

Кодировка, используемая org.apache.commons.fileupload при чтении заголовков запроса - это не UTF8, а, по-видимому, системная кодировка (в случае Windows - cp1251). Т.к. имена файлов передаются именно через заголовки (а именно, "Content-Disposition"), то неверное определение кодировки заголовка приводит к ломающейся кодировке имен файлов.

Решение:

Задать явно кодировку ServletFileUpload объекта вызовом метода setHeaderEncoding() перед парсингом запроса методом parseRequest():
FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF8");

четверг, 22 декабря 2011 г.

JSP и "multipart/form-data"-формы

"Из коробки" спецификация Servlet API 2.x не поддерживает автоматическое распознавание запросов "multipart/form-data", а, значит, например, Apache Tomcat версии, раньше 7ой, работать с ними также не умеет. В итоге, при передаче файла на JSP страницу среди параметров мы его не найдем. Выход - использовать контейнер сервлетов с поддержкой Servlet API 3.0 или воспользоваться сторонними разработками для работы с такими запросами. Например, Apache Commons FileUpload (Apache Commons FileUpload). Его использование состоит из следующих этапов:
1) В библиотеки добавить jar-ники самого commons-fileupload и commons-io (http://commons.apache.org/io/download_io.cgi).
2) На странице добавить импорты:
<%@ page import ="org.apache.commons.fileupload.*,org.apache.commons.fileupload.disk.*,org.apache.commons.fileupload.servlet.*" %>
3) Теперь в коде странице проверяем, является ли запрос мультипартовым, если да - обрабатываем его с помощью  Apache Commons FileUpload (подробнее про варианты обработки можно почитать тут - http://commons.apache.org/fileupload/using.html):

boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if(isMultipart)
{
// Создаем фабрику (при необходимости можно задать временную директорию и макс. размер файла)
FileItemFactory factory = new DiskFileItemFactory();
// Создаем обработчик
ServletFileUpload upload = new ServletFileUpload(factory);
// Парсим запрос
List /* FileItem */ items = upload.parseRequest(request);
// Обрабатываем результат
Iterator iter = items.iterator();
while (iter.hasNext())
{
FileItem item = (FileItem) iter.next();
if (item.isFormField()) // пропускаем не интересующие нас обычные поля формы
continue;
String fieldName = item.getFieldName();
String fileName = item.getName();
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
System.out.println("fieldName="+fieldName+",fileName="+fileName+",contentType="+contentType+",isInMemory="+isInMemory+",size="+sizeInBytes+"b");
/*
* Здесь делаем, например, item.getInputStream() и работаем с ним.
*/
}
}
else
{
// ...
}