NIHVIVO-3484 If an expected image file is not found, serve the "missing link" image instead.

This commit is contained in:
j2blake 2012-06-26 20:47:53 +00:00
parent a1a2771a05
commit b223feedb2
2 changed files with 84 additions and 45 deletions

View file

@ -2,8 +2,6 @@
package edu.cornell.mannlib.vitro.webapp.filestorage.serving; package edu.cornell.mannlib.vitro.webapp.filestorage.serving;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK; import static javax.servlet.http.HttpServletResponse.SC_OK;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -23,6 +21,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorage; import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorage;
import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup; import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup;
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo; import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
@ -48,6 +47,9 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
* </p> * </p>
*/ */
public class FileServingServlet extends VitroHttpServlet { public class FileServingServlet extends VitroHttpServlet {
/** If we can't locate the requested image, use this one instead. */
private static final String PATH_MISSING_LINK_IMAGE = "/images/missingLink.png";
private static final Log log = LogFactory.getLog(FileServingServlet.class); private static final Log log = LogFactory.getLog(FileServingServlet.class);
private FileStorage fileStorage; private FileStorage fileStorage;
@ -78,46 +80,28 @@ public class FileServingServlet extends VitroHttpServlet {
String path = request.getServletPath() + request.getPathInfo(); String path = request.getServletPath() + request.getPathInfo();
log.debug("Path is '" + path + "'"); log.debug("Path is '" + path + "'");
FileInfo fileInfo = FileInfo.instanceFromAliasUrl( /*
request.getFullWebappDaoFactory(), path, getServletContext()); * Get the mime type and an InputStream from the file. If we can't, use
log.debug("File info is '" + fileInfo + "'"); * the dummy image file instead.
if (fileInfo == null) { */
String message = "The request path is not valid for the File servlet: '"
+ path + "'";
log.error(message);
response.sendError(SC_INTERNAL_SERVER_ERROR, message);
return;
}
// Validate that the file exists, with the requested URI and filename.
String requestedFilename = getFilename(path);
String actualFilename = fileInfo.getFilename();
if (!actualFilename.equals(requestedFilename)
&& !actualFilename.equals(decode(requestedFilename))) {
log.warn("The requested filename does not match the "
+ "actual filename; request: '" + path + "', actual: '"
+ actualFilename + "'");
response.sendError(SC_NOT_FOUND, ("File not found: " + path));
return;
}
// Get the MIME type.
String mimeType = fileInfo.getMimeType();
// Open the actual byte stream.
InputStream in; InputStream in;
String mimeType = null;
try { try {
in = fileStorage.getInputStream(fileInfo.getBytestreamUri(), FileInfo fileInfo = figureFileInfo(
actualFilename); request.getFullWebappDaoFactory(), path);
} catch (FileNotFoundException e) { mimeType = fileInfo.getMimeType();
log.error("Expected file doesn't exist: " + e);
response.sendError(SC_INTERNAL_SERVER_ERROR, e.toString()); String actualFilename = findAndValidateFilename(fileInfo, path);
return;
in = openImageInputStream(fileInfo, actualFilename);
} catch (Exception e) {
log.warn("Failed to serve the file at '" + path + "' -- " + e.getMessage());
in = openMissingLinkImage(request);
} }
/* /*
* Everything is ready and working. Set the status and the content type, * Everything is ready. Set the status and the content type, and send
* and send the image bytes. * the image bytes.
*/ */
response.setStatus(SC_OK); response.setStatus(SC_OK);
@ -149,10 +133,36 @@ public class FileServingServlet extends VitroHttpServlet {
} }
} }
/** private FileInfo figureFileInfo(WebappDaoFactory fullWadf, String path)
* The filename is the portion of the path after the last slash. throws FileServingException {
*/ FileInfo fileInfo = FileInfo.instanceFromAliasUrl(fullWadf, path,
private String getFilename(String path) { getServletContext());
if (fileInfo == null) {
throw new FileServingException("The request path is not valid "
+ "for the File servlet: '" + path + "'");
}
log.debug("File info is '" + fileInfo + "'");
return fileInfo;
}
/** Validate that the file exists, with the requested URI and filename. */
private String findAndValidateFilename(FileInfo fileInfo, String path)
throws FileServingException {
String requestedFilename = figureFilename(path);
String actualFilename = fileInfo.getFilename();
if (!actualFilename.equals(requestedFilename)
&& !actualFilename.equals(decode(requestedFilename))) {
throw new FileServingException(
"The requested filename does not match the "
+ "actual filename; request: '" + path
+ "', actual: '" + actualFilename + "'");
}
log.debug("Actual filename is '" + actualFilename + "'");
return actualFilename;
}
/** The filename is the portion of the path after the last slash. */
private String figureFilename(String path) {
int slashHere = path.lastIndexOf('/'); int slashHere = path.lastIndexOf('/');
if (slashHere == -1) { if (slashHere == -1) {
return path; return path;
@ -161,18 +171,34 @@ public class FileServingServlet extends VitroHttpServlet {
} }
} }
/** /** The filename may have been encoded for URL transfer. */
* The filename may have been encoded for URL transfer.
*/
private String decode(String filename) { private String decode(String filename) {
try { try {
return URLDecoder.decode(filename, "UTF-8"); return URLDecoder.decode(filename, "UTF-8");
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
log.error("How did this happen?", e); log.error("No UTF-8 decoder? How did this happen?", e);
return filename; return filename;
} }
} }
private InputStream openImageInputStream(FileInfo fileInfo,
String actualFilename) throws IOException {
return fileStorage.getInputStream(fileInfo.getBytestreamUri(),
actualFilename);
}
/** Any suprises when opening the image? Use this one instead. */
private InputStream openMissingLinkImage(VitroRequest vreq)
throws FileNotFoundException {
InputStream stream = vreq.getSession().getServletContext()
.getResourceAsStream(PATH_MISSING_LINK_IMAGE);
if (stream == null) {
throw new FileNotFoundException("No image file at '"
+ PATH_MISSING_LINK_IMAGE + "'");
}
return stream;
}
/** /**
* A POST request is treated the same as a GET request. * A POST request is treated the same as a GET request.
*/ */
@ -182,4 +208,17 @@ public class FileServingServlet extends VitroHttpServlet {
doGet(request, response); doGet(request, response);
} }
/**
* There was a problem serving the file bytestream.
*/
private static class FileServingException extends Exception {
public FileServingException(String message) {
super(message);
}
public FileServingException(String message, Throwable cause) {
super(message, cause);
}
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB