Vaadin Запрошенный ресурс не найден

Мы разрабатываем приложение Vaadin, запуская его на oc4j 10.1.3. Есть окно, в котором результаты запроса можно экспортировать в виде файла csv. После создания CSV-файла в качестве vaadin FileResource открытие файла завершается ошибкой. Вот фрагмент:

File file = exporter.exportToFile();
final FileResource resource = new FileResource(file, getApplication());
resource.setCacheTime(0);
resource.getStream().setParameter("Content-Disposition", "attachment;filename=\""+file.getName()+"\"");
event.getButton().getWindow().open(resource);

На данный момент uri ресурса: app://APP/1/xy.csv

У нас есть фильтр для перенаправления пути "/" на "/VAADIN". Когда этот фильтр вызывается, uri файла равен /VAADIN/APP/1/xy.csv вместо /APP/1/xy.csv, поэтому я удаляю ненужную часть /VAADIN и вызываю requestdispatcher.forward с новым uri. Но вот самое интересное, приложение все равно не работает, в логе пишет:

Aug 13, 2012 1:55:58 PM com.vaadin.terminal.gwt.server.AbstractApplicationServlet serveStaticResourcesInVAADIN
INFO: Requested resource [VAADIN/APP/1/xy.csv] not found from filesystem or through class loader. Add widgetset and/or theme JAR to your classpath or add files to WebContent/VAADIN folder.

Итак, uri снова неверен. Он появляется в адресной строке, и приложение сбрасывается на главную страницу. Однако, когда этот uri все еще находится в адресной строке, когда я пытаюсь снова создать файл csv, выполняя любой из других запросов в приложении, часть экспорта возвращает файл, ранее сгенерированный. Если я попытаюсь снова выполнить другой запрос (с предыдущим URL-адресом, все еще находящимся в адресной строке браузера), он, похоже, сгенерирует новый файл csv, но снова вернет первый файл.

Это ошибка vaadin или какая-то магия oc4j? :)


person csaadaam    schedule 13.08.2012    source источник


Ответы (1)


Фреймворк Vaadin работает на стороне сервера. Так зачем вам создавать ненужные временные файлы CSV на сервере? Попробуйте экспортировать нужные данные прямо в поток.

Если вам нужно экспортировать небольшие объемы данных, просто используйте ByteArrayOutputStream и Vaadin StreamResource. Запишите свои значения CSV в OutputStream и дайте этому потоку функцию, как показано ниже:

    public void openResourceFromStream(final OutputStream out, String filename) {
    StreamSource streamSource = new StreamSource() {
        private static final long serialVersionUID = 1L;

        @Override
        public InputStream getStream() {
            ByteArrayOutputStream byteStream = (ByteArrayOutputStream) out;
            return new ByteArrayInputStream(byteStream.toByteArray());
        }
    };

    Resource sr = new StreamResource(streamSource, filename, getApplication());
    getWindow().open(sr, "_parent");
    }

Как видите, этот код выполняет простой обмен данными между OutputStream и InputStream и использует результат InputStream для создания объекта Vaadin StreamResource.

Параметр 'filename' устанавливает имя файла по умолчанию, которое будет загружено в браузер на стороне клиента (обратите внимание, что пользователь всегда может переименовывать файлы «на лету», используя опцию браузера «всегда отображать диалоги сохранения»).

Конечно, этот вариант немного уродлив, потому что он хранит все экспортированные данные в памяти.

Если вам нужно экспортировать большие объемы данных и вы не хотите хранить их все в памяти, вы можете использовать PipedOutputStream или пользовательские кольцевые буферы вместо байтового буфера ByteArrayOutputStream. Алгоритм будет тот же. См. статью о диалоге OutputStream с InputStream и глава книги Vaadin о ресурсах для получения дополнительной информации.

P.S. Не забудьте полностью закрыть потоки ввода и вывода после успешного экспорта данных.

person daniilyar    schedule 14.08.2012
comment
Спасибо за ваше предложение, но это то же самое. Как говорится в книге в этой главе, We named the resource as myimage.png. The application adds a resource key to the file name of the resource to make it unique. The full URI will be like http://localhost:8080/testbench/APP/1/myimage.png. Здесь то же самое, создает уникальный URI для потока, поскольку это файл, тот же плохой uri, и мой форвард по-прежнему бесполезен. И да, мы должны быть готовы к огромным объемам клиентских данных, поэтому преобразование выходной поток->массив байтов->входной поток неприемлемо из-за ограничений памяти. - person csaadaam; 15.08.2012
comment
У меня такая же проблема в Chrome, но не в Firefox. Вы уже решили эту проблему? - person Monir; 13.04.2013