spring-mvc (портлет): как вернуть PDF-файл в диалоговое окно открытия файла?

В моем @ActionMapping я создаю файл PDF для пользователя. Теперь мне было интересно, как я могу вернуть этот pdf пользователю в виде диалогового окна сохранения/открытия файла? Я бы предпочел это, а не показывать ссылку для скачивания, если генерация прошла успешно.

Я использую spring-mvc 3.0.5 в сочетании с портлетами. Но если у кого-то есть какие-то указатели для нормального приложения, я, вероятно, смогу понять это оттуда. Для 2.0 я читал что-то о расширении класса pdfgenerator и вращении в web.xml, но поскольку в настоящее время нам просто нужны POJO....


Изменить: код после предложения Адиля:

File file = new File("C:\\test.pdf");
        response.setContentType("application/pdf");

        try {
            byte[] b = new byte[(int) file.length()];
            OutputStream out = response.getPortletOutputStream();
            out.write(new FileInputStream(file).read(b));
            out.flush();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return "users/main";

person jack    schedule 04.01.2011    source источник


Ответы (4)


Вы можете записать этот файл прямо в свой response writer и не забудьте изменить файл contentType. Например,

response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment;filename=something.pdf");
OutputStream out = response.getOutputStream();
out.write(pdfFileContentInBytes);
out.flush();                   

Ну, я думал, что у тебя HttpServletResponse, но это не так. Поскольку вы работаете с портлетом, это объект RenderResponse. После поиска в Интернете я нашел несколько ссылок, которые могут быть вам полезны в этом отношении.

  • Сначала возьмем пример Портлет Lotus Form Server, в котором показано, как разрешить несколько типов mime при настройке портлета с помощью portlet.xml.

  • Вот документы Spring Portlet, в которых показано, как мы настраиваем портлет с помощью portlet.xml. В нем есть элемент XML о MIME-типе, посмотрите, можете ли вы указать там значение application/pdf.

Другая идея состоит в том, чтобы изменить ваш параметр на ActionResponse response вместо RenderResponse response. Я немного размыт здесь, не уверен, какой у тебя суперкласс? какой это метод? и т.д....

Мне кажется, что проблема в разрешенных/неразрешенных MIME-типах для ответа портлета.

person Adeel Ansari    schedule 04.01.2011
comment
чтобы добавить к ответу Адила .. тип контента должен быть application/pdf - person Mahesh; 04.01.2011
comment
@Mahesh: я как раз этим и занимался :). Спасибо, в любом случае. - person Adeel Ansari; 04.01.2011
comment
Только что попробовал это, и я получаю: приложение/pdf не поддерживается mime/типом. Но это, кажется, в правильном направлении. - person jack; 04.01.2011
comment
@Джек: Удивительно! Это допустимый MIME-тип. Проверьте это, tools.ietf.org/html/rfc3778. Однако попробуйте с application/octet-stream, это должно сработать. Но я бы все же предложил устранить неполадки, почему первый выдает ошибку. Возможно, мы сможем что-то сказать, если вы поделитесь фактическим кодом и сообщением об ошибке. - person Adeel Ansari; 04.01.2011
comment
Добавил немного кода. Я использую spring-portlet-mvc, поэтому у меня нет прямого доступа к HttpServletResponse (необходимому для setHeader, поскольку RenderResponse не имеет этой функции (вероятно, по какой-то причине). И это была фактическая ошибка. application/pdf не является поддерживаемый MIME-тип. - person jack; 04.01.2011
comment
Ммм, только что попробовал это приложение/октетный поток, и я получаю ОШИБКУ [jsp:154] java.lang.IllegalArgumentException: приложение/октетный поток не является поддерживаемым типом mime. Так что, если этот setHeader не требуется, происходит что-то более глубокое. - person jack; 04.01.2011
comment
@Jack: посмотрите, есть ли эта ветка, ibm.com/developerworks/forums/ thread.jspa?threadID=264854 дает некоторую идею/понимание. Кстати, это портлет Websphere. - person Adeel Ansari; 04.01.2011
comment
Адил, родительский класс - это просто Object. Как и в случае с spring-web-mvc, вы просто аннотируете POJO, чтобы использовать его в качестве контроллера spring-portlet-mvc. ActionResponse и RenderResponse — это просто разные этапы. Вы можете (не должны) иметь действие перед рендерингом. Действие на самом деле является действием, в то время как RenderMapping имеет отношение к отображению. Я попробую эти дополнительные типы пантомимы, когда у меня будет возможность. (немного заболочено в настоящее время) - person jack; 04.01.2011
comment
только что попробовал добавить дополнительные типы пантомимы, похоже, не помогло. Я посмотрю, не найду ли я завтра вечером немного времени, чтобы немного поэкспериментировать с ним. - person jack; 04.01.2011
comment
Когда я найду способ сделать это, я обновлю этот пост. Но кажется, что это невозможно сделать с помощью портлета. (Что немного логично, поскольку портлет является частью страницы, а не всей страницы, и поэтому имеет ограниченные возможности. Но было бы неплохо найти способ. - person jack; 07.01.2011
comment
@Jack: см. первый ответ здесь, он проливает свет, stackoverflow.com/questions/2361765/ - person Adeel Ansari; 07.01.2011
comment
Решение состоит в том, чтобы использовать механизм службы ресурсов, если вы используете JSR 286, или настроить сервлет, если вы собираетесь использовать портлеты JSR 168. Смотрите мой ответ для обоих решений. - person Ashok Goli; 24.01.2012

весной mvc, ответ ResourceResponse

response.reset();
response.setContentType("application/pdf");
response.setProperty("Content-disposition", "attachment; filename=\"" +"example.pdf" +"\"");

InputStream fontInputStream = request.getPortletSession()
                .getPortletContext()
                .getResourceAsStream("/WEB-INF/classes/arial.ttf");
Document document = new Document(PageSize.A4, 40, 40, 40, 50);
PdfWriter writer = PdfWriter.getInstance(document,
response.getPortletOutputStream());
document.addAuthor("XYZ");
document.addTitle("ASDF");
document.open();
person PeterR    schedule 21.06.2011
comment
setProperty() в качестве замены setHeader() в портлетах. Приятно знать, что это сработает. - person fishbone; 08.03.2016

Вот ответ после того, как я немного поработал над этим: Обслуживание PDF в архитектуре Spring Portlet MVC — Liferay 6.0.6

Решение состоит в том, чтобы использовать механизм обслуживания ресурсов из JSR 286. ResourceResponse res имеет метод res.setContentType("application/pdf");, поэтому вы можете использовать его для обслуживания ресурсов любого типа. Если вам нужно, чтобы он был загружен в виде вложения, то используйте это:

res.addProperty(HttpHeaders.CONTENT_DISPOSITION,"attachment");

person Ashok Goli    schedule 24.01.2012

Мой код:

Сопоставление ресурсов("получитьPDF")

public void descargarRecibo(ResourceRequest request,
        ResourceResponse response, PortletSession session,
        ModelMap modelMap) {
    FileInputStream fileInputStream = null;
    BufferedInputStream bufferedInputStream = null;

    String fileURL = "c:/intranetdoc/PDetalleLlamadas/file.pdf";

    try {
        fileInputStream = new java.io.FileInputStream(fileURL);
        OutputStream outputStream = response.getPortletOutputStream();
        response.setContentType("application/pdf");
        response.addProperty("Content-Disposition", "attachment; filename="
                + fileName);
        bufferedInputStream = new java.io.BufferedInputStream(
                fileInputStream);
        byte[] bytes = new byte[bufferedInputStream.available()];
        response.setContentLength(bytes.length);
        int aByte = 0;
        while ((aByte = bufferedInputStream.read()) != -1) {
            outputStream.write(aByte);
        }
        outputStream.flush();
        bufferedInputStream.close();
        response.flushBuffer();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
person user2009177    schedule 24.01.2013
comment
лол - извините - думал, что это был вопрос - однако было бы неплохо несколько слов вступления - person java_xof; 25.01.2013