Вернуть файл tiff из выходного потока на JSP

Я использую JSP для отображения одного файла TIFF. Поток выглядит следующим образом:

  1. Мне дают PDF для конвертации в TIFF.
  2. Я передаю API «черного ящика» PDF в виде объекта File и OutputStream (в настоящее время я использую ByteArrayOutputStream, но это может измениться по мере необходимости.
  3. «Черный ящик» преобразует PDF в TIFF и сохраняет результат в OutputStream.
  4. Я использую out.println(outputstream), чтобы выдать TIFF.

Проблема в том, что я получаю текстовый поток вместо отображаемого изображения. Я использовал следующий заголовок/метатег:

    <head><title>PDF to TIFF tester</title>
  <META HTTP-EQUIV="Content-Script-Type" CONTENT="image/tiff"></head>
  <body>

Но это не меняет конечного результата. Любая помощь?


person YYY    schedule 13.05.2010    source источник


Ответы (4)


Вы не должны использовать JSP для этого. Это технология представления, предоставляющая текстовый шаблон для размещения кода HTML/CSS/JS и средства для взаимодействия с бэкэнд-кодом Java с помощью taglibs (JSTL и т. д.) и EL (язык выражений, ${} вещи).

Изображение TIFF не является символьными (текстовыми) данными. Это двоичные данные. Вам действительно нужно использовать сервлет для этого. Вы не должны использовать методы Writer для возврата двоичных данных. Для этого следует использовать OutputStream методы. В противном случае двоичные данные будут повреждены (то же самое происходит и в JSP, так как он внутри использует Writer).

Вот пример того, как должен выглядеть ваш сервлет:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String pdfFilename = request.getParameter("filename");
    File pdfFile = new File("/path/to/all/pdf/files", pdfFilename);

    response.setHeader("Content-Type", "image/tiff");
    doYourThingToConvertPdfFileToTiff(pdfFile, response.getOutputStream());
}

Сопоставьте этот сервлет с url-pattern, например, /pdf2tiff, чтобы вы могли вызывать его с помощью http://example.com/contextname/pdf2tiff?filename=file.pdf в ссылках или адресной строке браузера или даже в атрибуте src элемента <img>.

doYourThingToConvertPdfFileToTiff - это ваш API-интерфейс "черного ящика", который, кажется, уже записывает TIFF в данный OutputStream. Просто используйте его и передайте один из HTTP-ответов.


Обновление: если вам действительно нужно использовать JSP для этого, вы можете просто написать тот же код в JSP, что и в классе сервлетов. Вы можете практически скопировать его. Только убедитесь, что вы не записываете в поток текст шаблона, включая разрывы строк и пробелы за пределами скриптлетов. В противном случае он также будет записан в двоичный файл и испортит его.

Если у вас есть несколько блоков скриптлета, вам нужно расположить их так, чтобы между конечным %> скриптлета и начальным <% следующего скриптлета не было разрыва строки. Таким образом, например.

<%@page import="java.io.File" %><%
    //...
%>

вместо

<%@page import="java.io.File" %>
<%
    //...
%>
person BalusC    schedule 13.05.2010
comment
Я бы с удовольствием использовал для этого сервлет, но мои коллеги были непреклонны в том, что мне не следует этого делать. Решение использовать JSP не было моим собственным. Кстати, я нашел способ обрабатывать кодировку из первой строки JSP; ‹%@ page language=java contentType=image/tiff; charset=UTF-8 pageEncoding=TIFF %› Однако это заставляет проект жаловаться на то, что он не поддерживается, чего я все время немного боялся увидеть. Я думаю, что этот вопрос может быть закрыт, пока я передам эти выводы своим коллегам. - person YYY; 13.05.2010
comment
Обновленный ответ. Кстати, я надеюсь, что вы поняли, что вам на самом деле следует делать с OutputStream. Не передавайте ByteArrayOutputStream, который вы массируете, обратно в InputStream позже, чтобы записать его в OutputStream ответа. Это просто неэффективно. Вы также действительно не можете print() экземпляр OutputStream, вы увидите только результат Object#toString() в ответе. - person BalusC; 13.05.2010
comment
Это абсолютно лучший способ сделать это, он может передавать PDF-файл клиенту по мере его растеризации (если ваш черный ящик поддерживает это). Это может сэкономить память. Однако не забудьте проверить, выполняет ли ваш черный ящик растеризацию на лету, особенно если у вас большое количество одновременных запросов. - person Justin; 13.05.2010

Это не сработает. Вам нужен тип контента http-ответа на изображение/tiff.

Для получения дополнительной информации: http://www.apl.jhu.edu/~hall/java/Servlet-Tutorial/Servlet-Tutorial-Response-Headers.html

person Midhat    schedule 13.05.2010
comment
Однако это совершенно другая установка по сравнению с тем, с чем я сталкиваюсь. JSP и сервлет — две совершенно разные вещи. Я не могу использовать объект ответа со встроенным кодом в JSP. Есть ли другой способ установить тип ответа? - person YYY; 13.05.2010
comment
как кто-то сказал, используйте сервлет - person Midhat; 13.05.2010

Метатег — это не то, на что смотрит браузер. Попробуйте использовать скриптлет, чтобы задать тип содержимого для объекта ответа. На этой странице есть несколько предложений.

person sblundy    schedule 13.05.2010

Если вы должны использовать JSP:

Вы можете сохранить выходной поток в файл со случайно сгенерированным именем, а затем сослаться на файл в JSP. Вам нужно убедиться, что выходной каталог находится в пути веб-сервера.

Это также сопряжено со своими проблемами:

  • Вам нужно управлять файловой системой таким образом, чтобы удалять старые файлы (поэтому диск вашего сервера будет заполнен).
  • Вам необходимо управлять синхронизацией с файлом (никакие два потока сервера не должны обновлять один и тот же файл).
  • Да, и вы должны убедиться, что изображения, созданные одним пользователем, не видны другому.

Я видел, как многие люди делали подобные вещи, я уверен, что есть библиотека.

person Justin    schedule 13.05.2010