Proof of concept - Image upload
This commit is contained in:
parent
c59076a19a
commit
bf2ed5c339
9 changed files with 248 additions and 63 deletions
|
@ -36,6 +36,7 @@ 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.ImageInfo;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServletRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
|
||||
|
||||
/**
|
||||
|
@ -48,6 +49,9 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
|
||||
private static final String ATTRIBUTE_REFERRING_PAGE = "ImageUploadController.referringPage";
|
||||
|
||||
private static final String ERROR_CODE_UNRECOGNIZED_URI = "imageUpload.errorUnrecognizedURI";
|
||||
private static final String ERROR_CODE_NO_URI = "imageUpload.errorNoURI";
|
||||
|
||||
/** Limit file size to 6 megabytes. */
|
||||
public static final int MAXIMUM_FILE_SIZE = 6 * 1024 * 1024;
|
||||
|
||||
|
@ -97,6 +101,14 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
|
||||
private static final String URL_HERE = UrlBuilder.getUrl("/uploadImages");
|
||||
|
||||
private static final String TEXT_BUNDLE = "imageUpload";
|
||||
private static final String TEXT_STRING_UPLOAD_TITLE = "upload_page_title";
|
||||
private static final String TEXT_STRING_UPLOAD_TITLE_WITH_NAME = "upload_page_title_with_name";
|
||||
private static final String TEXT_STRING_REPLACE_TITLE = "replace_page_title";
|
||||
private static final String TEXT_STRING_REPLACE_TITLE_WITH_NAME = "replace_page_title_with_name";
|
||||
private static final String TEXT_STRING_CROP_TITLE = "crop_page_title";
|
||||
private static final String TEXT_STRING_CROP_TITLE_WITH_NAME = "crop_page_title_with_name";
|
||||
|
||||
private FileStorage fileStorage;
|
||||
|
||||
/**
|
||||
|
@ -218,7 +230,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
}
|
||||
} catch (UserMistakeException e) {
|
||||
// Can't find the entity? Complain.
|
||||
return showAddImagePageWithError(vreq, null, e.getMessage());
|
||||
return showAddImagePageWithError(vreq, null, e.formatMessage(vreq));
|
||||
} catch (Exception e) {
|
||||
// We weren't expecting this - log it, and apologize to the user.
|
||||
return new ExceptionResponseValues(e);
|
||||
|
@ -274,7 +286,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
return showCropImagePage(vreq, entity,
|
||||
fileInfo.getBytestreamAliasUrl(), size);
|
||||
} catch (UserMistakeException e) {
|
||||
return showErrorMessage(vreq, entity, e.getMessage());
|
||||
return showErrorMessage(vreq, entity, e.formatMessage(vreq));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,6 +296,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
*/
|
||||
private ResponseValues showErrorMessage(VitroRequest vreq,
|
||||
Individual entity, String message) {
|
||||
|
||||
ImageInfo imageInfo = ImageInfo.instanceFromEntityUri(
|
||||
vreq.getFullWebappDaoFactory(), entity);
|
||||
if (imageInfo == null) {
|
||||
|
@ -313,7 +326,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
|
||||
return showExitPage(vreq, entity);
|
||||
} catch (UserMistakeException e) {
|
||||
return showErrorMessage(vreq, entity, e.getMessage());
|
||||
return showErrorMessage(vreq, entity, e.formatMessage(vreq));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,15 +363,14 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
throws UserMistakeException {
|
||||
String entityUri = vreq.getParameter(PARAMETER_ENTITY_URI);
|
||||
if (entityUri == null) {
|
||||
throw new UserMistakeException("No entity URI was provided");
|
||||
throw new UserMistakeException(ERROR_CODE_NO_URI);
|
||||
}
|
||||
|
||||
Individual entity = vreq.getFullWebappDaoFactory().getIndividualDao()
|
||||
.getIndividualByURI(entityUri);
|
||||
if (entity == null) {
|
||||
throw new UserMistakeException(
|
||||
"This URI is not recognized as belonging to anyone: '"
|
||||
+ entityUri + "'");
|
||||
throw new UserMistakeException(ERROR_CODE_UNRECOGNIZED_URI,
|
||||
entityUri);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
@ -416,7 +428,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
rv.put(BODY_THUMBNAIL_URL, placeholderUrl);
|
||||
rv.put(BODY_FORM_ACTION, formAction);
|
||||
rv.put(BODY_CANCEL_URL, cancelUrl);
|
||||
rv.put(BODY_TITLE, "Upload image" + forName(entity));
|
||||
rv.put(BODY_TITLE, figureUploadPageTitle(vreq, entity));
|
||||
rv.put(BODY_MAX_FILE_SIZE, MAXIMUM_FILE_SIZE / (1024 * 1024));
|
||||
rv.put(BODY_THUMBNAIL_HEIGHT, THUMBNAIL_HEIGHT);
|
||||
rv.put(BODY_THUMBNAIL_WIDTH, THUMBNAIL_WIDTH);
|
||||
|
@ -442,7 +454,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
rv.put(BODY_DELETE_URL, formAction(entity.getURI(), ACTION_DELETE_EDIT));
|
||||
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_UPLOAD));
|
||||
rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI()));
|
||||
rv.put(BODY_TITLE, "Replace image" + forName(entity));
|
||||
rv.put(BODY_TITLE, figureReplacePageTitle(vreq, entity));
|
||||
rv.put(BODY_MAX_FILE_SIZE, MAXIMUM_FILE_SIZE / (1024 * 1024));
|
||||
rv.put(BODY_THUMBNAIL_HEIGHT, THUMBNAIL_HEIGHT);
|
||||
rv.put(BODY_THUMBNAIL_WIDTH, THUMBNAIL_WIDTH);
|
||||
|
@ -472,7 +484,7 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
rv.put(BODY_MAIN_IMAGE_WIDTH, dimensions.width);
|
||||
rv.put(BODY_FORM_ACTION, formAction(entity.getURI(), ACTION_SAVE));
|
||||
rv.put(BODY_CANCEL_URL, exitPageUrl(vreq, entity.getURI()));
|
||||
rv.put(BODY_TITLE, "Crop Photo" + forName(entity));
|
||||
rv.put(BODY_TITLE, figureCropPageTitle(vreq, entity));
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -522,24 +534,59 @@ public class ImageUploadController extends FreemarkerHttpServlet {
|
|||
}
|
||||
|
||||
/**
|
||||
* Format the entity's name for display as part of the page title.
|
||||
* Format the title for the Upload page.
|
||||
*/
|
||||
private String forName(Individual entity) {
|
||||
private String figureUploadPageTitle(HttpServletRequest req,
|
||||
Individual entity) {
|
||||
return figurePageTitle(req, entity, TEXT_STRING_UPLOAD_TITLE,
|
||||
TEXT_STRING_UPLOAD_TITLE_WITH_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the title for the Replace page.
|
||||
*/
|
||||
private String figureReplacePageTitle(HttpServletRequest req,
|
||||
Individual entity) {
|
||||
return figurePageTitle(req, entity, TEXT_STRING_REPLACE_TITLE,
|
||||
TEXT_STRING_REPLACE_TITLE_WITH_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the title for the Crop page.
|
||||
*/
|
||||
private String figureCropPageTitle(HttpServletRequest req, Individual entity) {
|
||||
return figurePageTitle(req, entity, TEXT_STRING_CROP_TITLE,
|
||||
TEXT_STRING_CROP_TITLE_WITH_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format one of two page titles, depending on whether the entity has a
|
||||
* name.
|
||||
*/
|
||||
private String figurePageTitle(HttpServletRequest req, Individual entity,
|
||||
String noNameTitleKey, String nameTitleKey) {
|
||||
if (entity != null) {
|
||||
String name = entity.getName();
|
||||
if (name != null) {
|
||||
return " for " + name;
|
||||
return I18n.text(req, TEXT_BUNDLE, nameTitleKey, name);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
return I18n.text(req, TEXT_BUNDLE, noNameTitleKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds an error message to use as a complaint to the user.
|
||||
*/
|
||||
static class UserMistakeException extends Exception {
|
||||
UserMistakeException(String message) {
|
||||
private final Object[] parameters;
|
||||
|
||||
UserMistakeException(String message, Object... parameters) {
|
||||
super(message);
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public String formatMessage(HttpServletRequest req) {
|
||||
return I18n.text(req, getMessage(), parameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,18 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServ
|
|||
public class ImageUploadHelper {
|
||||
private static final Log log = LogFactory.getLog(ImageUploadHelper.class);
|
||||
|
||||
/*
|
||||
* Keys to text strings for error messages.
|
||||
*/
|
||||
private static final String ERROR_CODE_NO_IMAGE_TO_CROP = "imageUpload.errorNoImageForCropping";
|
||||
private static final String ERROR_CODE_IMAGE_TOO_SMALL = "imageUpload.errorImageTooSmall";
|
||||
private static final String ERROR_CODE_UNKNOWN = "imageUpload.errorUnknown";
|
||||
private static final String ERROR_CODE_FILE_TOO_BIG = "imageUpload.errorFileTooBig";
|
||||
private static final String ERROR_CODE_UNRECOGNIZED_FILE_TYPE = "imageUpload.errorUnrecognizedFileType";
|
||||
private static final String ERROR_CODE_NO_PHOTO_SELECTED = "imageUpload.errorNoPhotoSelected";
|
||||
private static final String ERROR_CODE_BAD_MULTIPART_REQUEST = "imageUpload.errorBadMultipartRequest";
|
||||
private static final String ERROR_CODE_FORM_FIELD_MISSING = "imageUpload.errorFormFieldMissing";
|
||||
|
||||
/**
|
||||
* When they upload a new image, store it as this session attribute until
|
||||
* we're ready to attach it to the Individual.
|
||||
|
@ -127,35 +139,31 @@ public class ImageUploadHelper {
|
|||
Object exception = request.getAttribute(FILE_UPLOAD_EXCEPTION);
|
||||
if (exception != null) {
|
||||
int limit = MAXIMUM_FILE_SIZE / (1024 * 1024);
|
||||
throw new UserMistakeException(
|
||||
"Please upload an image smaller than " + limit
|
||||
+ " megabytes");
|
||||
throw new UserMistakeException(ERROR_CODE_FILE_TOO_BIG, limit);
|
||||
}
|
||||
|
||||
Map<String, List<FileItem>> map = (Map<String, List<FileItem>>) request
|
||||
.getAttribute(FILE_ITEM_MAP);
|
||||
if (map == null) {
|
||||
throw new IllegalStateException("Failed to parse the "
|
||||
+ "multi-part request for uploading an image.");
|
||||
throw new IllegalStateException(ERROR_CODE_BAD_MULTIPART_REQUEST);
|
||||
}
|
||||
List<FileItem> list = map.get(PARAMETER_UPLOADED_FILE);
|
||||
if ((list == null) || list.isEmpty()) {
|
||||
throw new UserMistakeException("The form did not contain a '"
|
||||
+ PARAMETER_UPLOADED_FILE + "' field.");
|
||||
throw new UserMistakeException(ERROR_CODE_FORM_FIELD_MISSING,
|
||||
PARAMETER_UPLOADED_FILE);
|
||||
}
|
||||
|
||||
FileItem file = list.get(0);
|
||||
if (file.getSize() == 0) {
|
||||
throw new UserMistakeException("Please browse and select a photo.");
|
||||
throw new UserMistakeException(ERROR_CODE_NO_PHOTO_SELECTED);
|
||||
}
|
||||
|
||||
String filename = getSimpleFilename(file);
|
||||
String mimeType = getMimeType(file);
|
||||
if (!RECOGNIZED_FILE_TYPES.containsValue(mimeType)) {
|
||||
log.debug("Unrecognized MIME type: '" + mimeType + "'");
|
||||
throw new UserMistakeException("'" + filename
|
||||
+ "' is not a recognized image file type. "
|
||||
+ "Please upload JPEG, GIF, or PNG files only.");
|
||||
throw new UserMistakeException(ERROR_CODE_UNRECOGNIZED_FILE_TYPE,
|
||||
filename);
|
||||
}
|
||||
|
||||
return file;
|
||||
|
@ -221,10 +229,8 @@ public class ImageUploadHelper {
|
|||
|
||||
if ((size.height < THUMBNAIL_HEIGHT)
|
||||
|| (size.width < THUMBNAIL_WIDTH)) {
|
||||
throw new UserMistakeException(
|
||||
"The uploaded image should be at least "
|
||||
+ THUMBNAIL_HEIGHT + " pixels high and "
|
||||
+ THUMBNAIL_WIDTH + " pixels wide.");
|
||||
throw new UserMistakeException(ERROR_CODE_IMAGE_TOO_SMALL,
|
||||
THUMBNAIL_HEIGHT, THUMBNAIL_WIDTH);
|
||||
}
|
||||
|
||||
return size;
|
||||
|
@ -237,8 +243,7 @@ public class ImageUploadHelper {
|
|||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.warn("Unexpected exception in image handling", e);
|
||||
throw new UserMistakeException("Sorry, we were unable to process "
|
||||
+ "the photo you provided. Please try another photo.");
|
||||
throw new UserMistakeException(ERROR_CODE_UNKNOWN);
|
||||
} finally {
|
||||
if (source != null) {
|
||||
try {
|
||||
|
@ -261,8 +266,7 @@ public class ImageUploadHelper {
|
|||
ATTRIBUTE_TEMP_FILE);
|
||||
|
||||
if (fileInfo == null) {
|
||||
throw new UserMistakeException(
|
||||
"There is no image file to be cropped.");
|
||||
throw new UserMistakeException(ERROR_CODE_NO_IMAGE_TO_CROP);
|
||||
}
|
||||
|
||||
return fileInfo;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue