Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > Экспорт файла при помощи сервлета


Автор: vzf 19.7.2007, 16:33
У меня есть сервлет. Он получает из атрибута сессии массив байт соответствующий файлу. Вопрос как лучше передать этот файл в респонс?  Что лучше использовать OutputStream

Код

byte[] exportData = (byte[])session.getAttribute(session.getId() + SESSION_KEY);
response.getOutputStream().write(exportData);



или лучше открывать файл в сервлете  и использовать Writer ?

   
Код

                FileInputStream in = new FileInputStream(fileName);
                PrintWriter out = response.getWriter();
                InputStreamReader reader = new InputStreamReader(in);
                char[] buffer = new char[1024];
                int read;
                
                while((read = reader.read(buffer)) != -1){
                    out.write(buffer, 0, read);
                }
                
                out.flush();
                out.close();
                in.close();



Автор: AntonSaburov 19.7.2007, 16:41
Если побайтно, то надо открывать не Writer а OutputStream - это раз.

А также хорошо бы предварительно устанавливать MIME-type

response.setContentType("application/....."); // чего-то реальное - 

Тогда броузер попытается предложить записать файл на диск или открыть с помощью какого-либо приложения.

Автор: necromancer 19.7.2007, 16:45
между Writer и OutputStream по спецификации одна разница - тип передаваемых данных.
В первом случае это chars во втором это bytes.

Но проблема будет скорее даже не в этом, если предварителньо не сделать кое какие операции,
 то поток будет выведен в виде HTML страницы с неким набором непонятных символов.

Теперь следующее:
Если ты в поток пишешь просто HTML код, то тебе в принципе подойдут оба метода.
Если же ты пишешь binary данные то тебе к OutputStream.

А если ты ко всему прочему хочешь что бы появился диалог сохранения то:
Код

res.setContentType( "application/octet-stream" );
res.setHeader("Content-Disposition","attachment; filename=\"" + noname + "\"");
res.setHeader( "Pragma", "public" );
res.setContentLength(bytes.length);

Вместо octet-stream можно использовать соответсвующий тип документа, для ворда - msword

PS Эх штурман опередил =)
Но у меня есть ссылочка :Р на дисскусия на сан форуме http://forum.java.sun.com/thread.jspa?threadID=586671&start=15

Автор: AntonSaburov 19.7.2007, 16:49
Цитата(necromancer @  19.7.2007,  16:45 Найти цитируемый пост)
Эх штурман опередил =)

Да ладно - у тебя зато более подробно. Так что зачот smile

Автор: vzf 19.7.2007, 16:51
Content-type я устанавливаю тот который мне нужен c этим проблем нет. Хотелось бы услышать мнене какой подход лучше. Передавать массив байт сервлету, чтобы тот положил его в респонс при помощи OutPutStream или использовать Writer. Передававть лучше не побайтно.

Еще попутный вопрос что лучше использовать для "попадания" на сервлет в JSF (точнее в Facelets) :

outputLink
commandLink
commandButton

Просто иногда я получаю ошибку response already in use при редиректе на сревлет. Думаю может проблема в том как я файл записываю в респонс.

Добавлено через 5 минут и 17 секунд
Пока писал свое сообщение пропустил пару сообщений. итого для экспорта бинарных данных мне лучше использовать OutputStraem , я правильно понял ? Сейчас у меня  сервлет экспортирует и экселевские файлы и текстовые файлы лога, используя OutPutStream. 

Автор: AntonSaburov 19.7.2007, 17:26
Правильно понял. Правда Excel ныне неплохо понимает и обычный HTML, но для надежности smile

Автор: necromancer 19.7.2007, 17:48
Цитата

Еще попутный вопрос что лучше использовать для "попадания" на сервлет в JSF (точнее в Facelets) :

outputLink
commandLink
commandButton


outputLink представляет собой что то вроде <a href="">text</a>
остальные компоненты (commandLink, commandButton) делаю form.submit() - т.е. "попадают" в JSF

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)