EDIT: The reason for this issue was due to bug unrelated to the servlet.
I'm working on a JSF2/JPA/EJB3 project that enables users to upload photos of themselves and stores them in a database. Loading images from the database is made possible with a servlet. There is however a problem; when changing the picture and posting the page, the image goes blank. The servlet doesn't seem to be called.
Web page:
<h:form>
<h:graphicImage value="image?fileId=#{bean.currentUser.photo.id}"/>
<3rd party file upload component (primeFaces)/>
<h:commandButton value="post"/>
</h:form>
Servlet mapping:
<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>
Servlet:
@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 = userBea开发者_如何学Pythonn.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();
}
}
}
My guess is that doGet in ImageServlet is only called on Get. Forcing a new GET with faces-redirect=true works, but is it possible to make the servlet work on POST aswell?
You seem to think that images are downloaded as part of the HTTP response containing the HTML page containing the <img>
elements. This is not true. The browser obtains the HTML page, parses the HTML structure, encounters the <img>
element and fires separate HTTP requests for each of them. It is always GET. The same applies to CSS/JS and other resources. Install a HTTP request debugger tool like Firebug and check the Net panel.
The actual problem is likely that the URL as definied in src
attribute is wrong. You're using a context-relative path (i.e. no leading slash and no domain in the src
attribute, it's fully dependent on the current request URL -the one in browser address bar). Probably the HTML page get posted to a different context/folder which caused that the image becomes unreachable from that point. Try using an absolute path or a domain-relative path.
<h:graphicImage value="#{request.contextPath}/image?fileId=#{bean.currentUser.photo.id}" />
If still in vain, then have a closer look at Firebug's analysis.
精彩评论