【问题标题】:Problem showing image from a database with JSF via a Servlet通过 Servlet 使用 JSF 显示数据库中的图像时出现问题
【发布时间】:2011-06-06 09:33:52
【问题描述】:

编辑:此问题的原因是与 servlet 无关的错误。

我正在开发一个 JSF2/JPA/EJB3 项目,该项目使用户能够上传自己的照片并将其存储在数据库中。使用 servlet 可以从数据库加载图像。但是有一个问题;更改图片并发布页面时,图像变为空白。 servlet 似乎没有被调用。

网页:

<h:form>
    <h:graphicImage value="image?fileId=#{bean.currentUser.photo.id}"/>
    <3rd party file upload component (primeFaces)/>
    <h:commandButton value="post"/>
</h:form>

Servlet 映射:

<servlet>
    <servlet-name>imageServlet</servlet-name>
    <servlet-class>com.xdin.competence.jsf.util.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>imageServlet</servlet-name>
    <url-pattern>/image/*</url-pattern>
</servlet-mapping>

小服务程序:

@ManagedBean
public class ImageServlet extends HttpServlet {
    private static final int DEFAULT_BUFFER_SIZE = 10240; // 10KB.
    @EJB private UserBean userBean;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException
    {
        Long fileId = Long.parseLong(request.getParameter("fileId"));
        if (fileId == null) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND); // 404.
        return;
        }
        UserFile photo = userBean.findUserFile(fileId);
        // Init servlet response.
        response.reset();
        response.setBufferSize(DEFAULT_BUFFER_SIZE);
        response.setContentType("image/png");
        response.setHeader("Content-Length", String.valueOf(photo.getFileData().length));
        response.setHeader("Content-Disposition", "inline; filename=\"" + photo.getFilename() + "\"");

        // Prepare streams.
        BufferedInputStream input = null;
        BufferedOutputStream output = null;

        try {
            // Open streams.
            input = new BufferedInputStream(new ByteArrayInputStream(photo.getFileData()), DEFAULT_BUFFER_SIZE);
            output = new BufferedOutputStream(response.getOutputStream(), DEFAULT_BUFFER_SIZE);

            // Write file contents to response.
            byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
            int length;
            while ((length = input.read(buffer)) > 0) {
                output.write(buffer, 0, length);
            }
        } finally {
            // Gently close streams.
            close(output);
            close(input);
        }
    }

    private static void close(Closeable resource) {
        if (resource != null) {
            try {
                resource.close();
            } catch (IOException e) {
                // Do your thing with the exception. Print it, log it or mail it.
                e.printStackTrace();
            }
        }
    }

我的猜测是 ImageServlet 中的 doGet 仅在 Get 上调用。使用 faces-redirect=true 强制一个新的 GET 是可行的,但是是否可以让 servlet 也可以在 POST 上工作?

【问题讨论】:

    标签: jsf servlets jsf-2


    【解决方案1】:

    您似乎认为图像是作为 HTTP 响应的一部分下载的,该响应包含包含 &lt;img&gt; 元素的 HTML 页面。这不是真的。浏览器获取 HTML 页面,解析 HTML 结构,遇到 &lt;img&gt; 元素并为每个元素触发 separate HTTP 请求。 总是 GET。这同样适用于 CSS/JS 和其他资源。安装一个 HTTP 请求调试器工具,如 Firebug 并检查 Net 面板。

    实际问题很可能是src属性中定义的URL错误。您正在使用上下文相关路径(即src 属性中没有前导斜杠和域,它完全取决于当前请求 URL - 浏览器地址栏中的那个)。可能 HTML 页面被发布到不同的上下文/文件夹,这导致图像从那时起变得无法访问。尝试使用绝对路径或域相对路径。

    <h:graphicImage value="#{request.contextPath}/image?fileId=#{bean.currentUser.photo.id}" />
    

    如果仍然无效,请仔细查看 Firebug 的分析。

    【讨论】:

    • 事实证明,这是我的控制器中的一个错误,导致 currentUser 过时; value="image?fileId=..." 在这种特定情况下有效,因为网页位于根目录中。仍然感谢您的回答,我对帖子后如何获取图像有点困惑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-13
    • 2022-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多