Document upload
This commit is contained in:
parent
e48b2d7e0f
commit
9e5236c712
14 changed files with 653 additions and 1 deletions
|
@ -0,0 +1,435 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||
|
||||
import static edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest.UNAUTHORIZED;
|
||||
import static edu.cornell.mannlib.vitro.webapp.controller.freemarker.ImageUploadController.PARAMETER_UPLOADED_FILE;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.jena.ontology.OntModel;
|
||||
import org.apache.tika.Tika;
|
||||
import org.apache.tika.mime.MimeType;
|
||||
import org.apache.tika.mime.MimeTypeException;
|
||||
import org.apache.tika.mime.MimeTypes;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.AuthorizationRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.RequestedAction;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.AddObjectPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropObjectPropertyStatement;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Property;
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.RedirectResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.UploadedFileHelper;
|
||||
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
|
||||
import edu.cornell.mannlib.vitro.webapp.i18n.I18n;
|
||||
import edu.cornell.mannlib.vitro.webapp.modules.fileStorage.FileStorage;
|
||||
|
||||
@WebServlet(name = "FileUploadController", urlPatterns = { "/uploadFile" })
|
||||
public class FileUploadController extends FreemarkerHttpServlet {
|
||||
private static final String TEMPLATE_VAR_FORM_ACTION = "formAction";
|
||||
private static final String TEMPLATE_VAR_MAX_FILE_SIZE = "maxFileSize";
|
||||
private static final String PARAM_REFERRER = "referrer";
|
||||
private static final String TEMPLATE_VAR_SUPPORTED_TYPES = "supportedTypes";
|
||||
private static final String TEMPLATE_VAR_SUPPORTED_MIME_TYPES = "supportedMIMETypes";
|
||||
|
||||
private static final String TEMPLATE_VAR_ERROR_MESSAGE = "errorMessage";
|
||||
private static final String DEFAULT_FILE_NAME = "fileName";
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final Log log = LogFactory.getLog(FileUploadController.class);
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String PARAMETER_ACTION = "action";
|
||||
private static final String ACTION_DELETE = "delete";
|
||||
private static final String ACTION_UPLOAD = "upload";
|
||||
private static final String PARAMETER_FILE_URI = "fileUri";
|
||||
private static final String PARAMETER_SUBJECT_URI = "subjectUri";
|
||||
private static final String CONFIG_MAX_FILE_SIZE = "fileUpload.maxFileSize";
|
||||
private static final String ALLOWED_MIME_TYPES = "fileUpload.allowedMIMETypes";
|
||||
private static final Long DEFAULT_FILE_SIZE = (long) (10 * 1024 * 1024);
|
||||
private static final String PARAMETER_PREDICATE_URI = "predicateUri";
|
||||
private static final String DEFAULT_TEMPLATE = "fileUpload-default.ftl";
|
||||
private static Long maxFileSize = DEFAULT_FILE_SIZE;
|
||||
private FileStorage fileStorage;
|
||||
private Set<String> allowedMimeTypes;
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException {
|
||||
super.init();
|
||||
fileStorage = ApplicationUtils.instance().getFileStorage();
|
||||
setMaxFileSize();
|
||||
setAllowedMimeTypes();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthorizationRequest requiredActions(VitroRequest vreq) {
|
||||
RequestedAction ra;
|
||||
try {
|
||||
Property predicate = new Property(getPredicateUri(vreq));
|
||||
final OntModel jenaOntModel = vreq.getJenaOntModel();
|
||||
final String subject = getSubjectUri(vreq);
|
||||
if (isUpload(vreq)) {
|
||||
ra = new AddObjectPropertyStatement(jenaOntModel, subject, predicate,RequestedAction.SOME_URI);
|
||||
} else { // delete
|
||||
ra = new DropObjectPropertyStatement(jenaOntModel, subject, predicate, getFileUri(vreq));
|
||||
}
|
||||
return ra;
|
||||
} catch (Exception e) {
|
||||
return UNAUTHORIZED;
|
||||
}
|
||||
}
|
||||
|
||||
private String getFileUri(VitroRequest vreq) {
|
||||
return vreq.getParameter(PARAMETER_FILE_URI);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResponseValues processRequest(VitroRequest vreq) {
|
||||
try {
|
||||
getReferrer(vreq);
|
||||
validateRequest(vreq);
|
||||
if (isUpload(vreq)) {
|
||||
uploadFile(vreq);
|
||||
} else if (isDelete(vreq)) {
|
||||
deleteFile(vreq);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return pageResponse(vreq, e.getMessage());
|
||||
}
|
||||
return new RedirectResponseValues(getNextPageUrl(vreq), HttpServletResponse.SC_SEE_OTHER);
|
||||
}
|
||||
private String getNextPageUrl(VitroRequest vreq) {
|
||||
return getReferrer(vreq);
|
||||
}
|
||||
|
||||
private TemplateResponseValues pageResponse(VitroRequest vreq, String error) {
|
||||
TemplateResponseValues rv = new TemplateResponseValues(DEFAULT_TEMPLATE);
|
||||
rv.put(PARAMETER_ACTION, vreq.getParameter(PARAMETER_ACTION));
|
||||
rv.put(TEMPLATE_VAR_FORM_ACTION, formatRequestUrl(vreq));
|
||||
if (!error.isEmpty()) {
|
||||
rv.put(TEMPLATE_VAR_ERROR_MESSAGE, error);
|
||||
}
|
||||
rv.put(PARAM_REFERRER,getReferrer(vreq));
|
||||
rv.put(TEMPLATE_VAR_SUPPORTED_TYPES, printAllowedFileExtensions());
|
||||
rv.put(TEMPLATE_VAR_SUPPORTED_MIME_TYPES, printAllowedMimeTypes());
|
||||
rv.put(TEMPLATE_VAR_MAX_FILE_SIZE, maxFileSizeInMegabytes());
|
||||
return rv;
|
||||
}
|
||||
|
||||
private String formatRequestUrl(VitroRequest vreq) {
|
||||
String result = vreq.getRequestURL().toString() + "?";
|
||||
String query = vreq.getQueryString();
|
||||
if (query != null) {
|
||||
result += query;
|
||||
}
|
||||
String referrer = vreq.getParameter(PARAM_REFERRER);
|
||||
if (referrer == null || referrer.isEmpty()) {
|
||||
result += "&" + PARAM_REFERRER + "=" + getReferrer(vreq);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Double maxFileSizeInMegabytes() {
|
||||
if (maxFileSize > 0) {
|
||||
return ((double) maxFileSize/1048576);
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
private void validateRequest(VitroRequest vreq) throws FileUploadException {
|
||||
if (isUpload(vreq)) {
|
||||
validateUploadRequest(vreq);
|
||||
} else if (isDelete(vreq)) {
|
||||
validateDeleteRequest(vreq);
|
||||
} else if (hasAction(vreq)) {
|
||||
throw new FileUploadException("Only delete and upload actions supported");
|
||||
} else {
|
||||
throw new FileUploadException("No action specified");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDeleteRequest(VitroRequest vreq) throws FileUploadException {
|
||||
validateSubjectUri(vreq);
|
||||
validatePredicateUri(vreq);
|
||||
validateFileUri(vreq);
|
||||
}
|
||||
|
||||
private void validateUploadRequest(VitroRequest vreq) throws FileUploadException {
|
||||
validateSubjectUri(vreq);
|
||||
validatePredicateUri(vreq);
|
||||
validateFile(vreq);
|
||||
}
|
||||
|
||||
private void validateFile(VitroRequest vreq) throws FileUploadException {
|
||||
Map<String, List<FileItem>> map = vreq.getFiles();
|
||||
if (map == null) {
|
||||
throw new FileUploadException("File to upload not found");
|
||||
}
|
||||
List<FileItem> list = map.get(PARAMETER_UPLOADED_FILE);
|
||||
if ((list == null) || list.isEmpty()) {
|
||||
throw new FileUploadException("No file uploaded");
|
||||
}
|
||||
FileItem file = list.get(0);
|
||||
if (file.getSize() == 0) {
|
||||
throw new FileUploadException("Uploaded file size is 0");
|
||||
}
|
||||
if (file.getSize() > maxFileSize) {
|
||||
throw new FileUploadException("Uploaded file is too big. Maximum file size is " + maxFileSize
|
||||
+ " bytes. Uploaded file is " + file.getSize() + " bytes.");
|
||||
}
|
||||
validateMimeType(file);
|
||||
}
|
||||
|
||||
private void validateMimeType(FileItem file) throws FileUploadException {
|
||||
String mime = getMimeType(file);
|
||||
if (mime.isEmpty()) {
|
||||
throw new FileUploadException("File type is unrecognized");
|
||||
}
|
||||
String extension = null;
|
||||
MimeTypes types = MimeTypes.getDefaultMimeTypes();
|
||||
try {
|
||||
MimeType mimeType = types.forName(mime);
|
||||
extension = mimeType.getExtension();
|
||||
} catch (MimeTypeException e) {
|
||||
log.error(e.getLocalizedMessage());
|
||||
}
|
||||
if (extension == null || extension.isEmpty()) {
|
||||
throw new FileUploadException("Extension for mime type " + mime + " not found");
|
||||
}
|
||||
if (!allowedMimeTypes.contains(mime.toLowerCase())) {
|
||||
log.error("File mime type is not allowed. " + printAllowedMimeTypes() + " Current mime type is " + mime);
|
||||
throw new FileUploadException(
|
||||
"File type is not allowed. Allowed file types: " + printAllowedFileExtensions() +
|
||||
" Current file type is " + getExtension(mime).replaceAll("\\.", ""));
|
||||
}
|
||||
}
|
||||
|
||||
private String printAllowedFileExtensions() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Iterator<String> it = allowedMimeTypes.iterator(); it.hasNext();) {
|
||||
String mimeType = (String) it.next();
|
||||
String extension = getExtension(mimeType);
|
||||
sb.append(extension.replaceAll("\\.", ""));
|
||||
if (it.hasNext()) {
|
||||
sb.append(", ");
|
||||
} else {
|
||||
sb.append(".");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String printAllowedMimeTypes() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Iterator<String> it = allowedMimeTypes.iterator(); it.hasNext();) {
|
||||
String mimeType = (String) it.next();
|
||||
sb.append(mimeType);
|
||||
if (it.hasNext()) {
|
||||
sb.append(", ");
|
||||
} else {
|
||||
sb.append(".");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private boolean hasAction(VitroRequest vreq) {
|
||||
return vreq.getParameter(PARAMETER_ACTION) != null;
|
||||
}
|
||||
|
||||
private void deleteFile(VitroRequest vreq) {
|
||||
String subjectUri = getSubjectUri(vreq);
|
||||
String predicateUri = getPredicateUri(vreq);
|
||||
String fileUri = getFileUri(vreq);
|
||||
WebappDaoFactory webAppDaoFactory = vreq.getUnfilteredWebappDaoFactory();
|
||||
UploadedFileHelper fileHelper = new UploadedFileHelper(fileStorage, webAppDaoFactory, getServletContext());
|
||||
fileHelper.removeUploadedFile(subjectUri, predicateUri, fileUri);
|
||||
}
|
||||
|
||||
private void uploadFile(VitroRequest vreq) throws FileUploadException {
|
||||
String subjectUri = getSubjectUri(vreq);
|
||||
String predicateUri = getPredicateUri(vreq);
|
||||
FileItem file = getUploadedFile(vreq);
|
||||
String uploadedFileName = getUploadedFileName(file);
|
||||
String storedFileName = createStoredFileName(file);
|
||||
WebappDaoFactory webAppDaoFactory = vreq.getUnfilteredWebappDaoFactory();
|
||||
UploadedFileHelper fileHelper = new UploadedFileHelper(fileStorage, webAppDaoFactory, getServletContext());
|
||||
FileInfo fileInfo = createFile(file, storedFileName, fileHelper);
|
||||
fileHelper.attachFileToSubject(fileInfo, subjectUri, predicateUri);
|
||||
fileHelper.setPublicFileName(fileInfo, uploadedFileName);
|
||||
}
|
||||
|
||||
private FileInfo createFile(FileItem file, String storedFileName, UploadedFileHelper fileHelper)
|
||||
throws FileUploadException {
|
||||
FileInfo fileInfo = null;
|
||||
try {
|
||||
fileInfo = fileHelper.createFile(storedFileName, getMimeType(file), file.getInputStream());
|
||||
} catch (Exception e) {
|
||||
log.error(e.getLocalizedMessage());
|
||||
throw new FileUploadException(e.getLocalizedMessage());
|
||||
}
|
||||
return fileInfo;
|
||||
}
|
||||
|
||||
private String createStoredFileName(FileItem file) {
|
||||
String mimeString = getMimeType(file);
|
||||
int length = 64;
|
||||
boolean useLetters = true;
|
||||
boolean useNumbers = true;
|
||||
String storedFileName = RandomStringUtils.random(length, useLetters, useNumbers) + getExtension(mimeString);
|
||||
return storedFileName;
|
||||
}
|
||||
|
||||
private String getExtension(String mimeString) {
|
||||
String extension = "";
|
||||
MimeTypes types = MimeTypes.getDefaultMimeTypes();
|
||||
try {
|
||||
MimeType mime = types.forName(mimeString);
|
||||
extension = mime.getExtension();
|
||||
} catch (MimeTypeException e) {
|
||||
log.error(e.getLocalizedMessage());
|
||||
}
|
||||
return extension;
|
||||
}
|
||||
|
||||
private String getUploadedFileName(FileItem file) {
|
||||
String fileName = file.getName();
|
||||
if (fileName == null) {
|
||||
return DEFAULT_FILE_NAME;
|
||||
} else {
|
||||
return FilenameUtils.getName(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
private String getMimeType(FileItem file) {
|
||||
Tika tika = new Tika();
|
||||
InputStream is;
|
||||
String mime = "";
|
||||
try {
|
||||
is = file.getInputStream();
|
||||
mime = tika.detect(is);
|
||||
} catch (IOException e) {
|
||||
log.error(e.getLocalizedMessage());
|
||||
}
|
||||
return mime;
|
||||
}
|
||||
|
||||
private void validateFileUri(VitroRequest vreq) throws FileUploadException {
|
||||
String fileUri = getFileUri(vreq);
|
||||
validateUriNotEmpty(fileUri,"file");
|
||||
validateIndividual(vreq, fileUri);
|
||||
}
|
||||
|
||||
private void validateSubjectUri(VitroRequest vreq) throws FileUploadException {
|
||||
String subjectUri = getSubjectUri(vreq);
|
||||
validateUriNotEmpty(subjectUri,"subject");
|
||||
validateIndividual(vreq, subjectUri);
|
||||
}
|
||||
|
||||
private void validatePredicateUri(VitroRequest vreq) throws FileUploadException {
|
||||
String predicateUri = getPredicateUri(vreq);
|
||||
validateUriNotEmpty(predicateUri,"predicate");
|
||||
validateIndividual(vreq, predicateUri);
|
||||
}
|
||||
|
||||
private void validateIndividual(VitroRequest vreq, String subjectUri) throws FileUploadException {
|
||||
Individual subject = vreq.getUnfilteredWebappDaoFactory().getIndividualDao()
|
||||
.getIndividualByURI(subjectUri);
|
||||
if (subject == null) {
|
||||
throw new FileUploadException("Uri " + subjectUri + "doesn't exist");
|
||||
}
|
||||
}
|
||||
|
||||
private void validateUriNotEmpty(String predicateUri,String name) throws FileUploadException {
|
||||
if (predicateUri == null || predicateUri.trim().isEmpty()) {
|
||||
throw new FileUploadException("No " + name + " uri was given");
|
||||
}
|
||||
}
|
||||
|
||||
private String getPredicateUri(VitroRequest vreq) {
|
||||
return vreq.getParameter(PARAMETER_PREDICATE_URI);
|
||||
}
|
||||
|
||||
private String getSubjectUri(VitroRequest vreq) {
|
||||
return vreq.getParameter(PARAMETER_SUBJECT_URI);
|
||||
}
|
||||
|
||||
private FileItem getUploadedFile(VitroRequest vreq) {
|
||||
return vreq.getFiles().get(PARAMETER_UPLOADED_FILE).get(0);
|
||||
}
|
||||
|
||||
private boolean isUpload(VitroRequest vreq) {
|
||||
String action = vreq.getParameter(PARAMETER_ACTION);
|
||||
return ACTION_UPLOAD.equals(action);
|
||||
}
|
||||
|
||||
private boolean isDelete(VitroRequest vreq) {
|
||||
String action = vreq.getParameter(PARAMETER_ACTION);
|
||||
return ACTION_DELETE.equals(action);
|
||||
}
|
||||
|
||||
private void setAllowedMimeTypes() {
|
||||
ConfigurationProperties config = ConfigurationProperties.getBean(getServletContext());
|
||||
String allowedTypes = config.getProperty(ALLOWED_MIME_TYPES, "");
|
||||
allowedMimeTypes = new HashSet<String>(Arrays.asList(allowedTypes.toLowerCase().trim().split("\\s*,\\s*")));
|
||||
}
|
||||
|
||||
private String getReferrer(VitroRequest vreq) {
|
||||
String referrer = vreq.getParameter(PARAM_REFERRER);
|
||||
if (referrer == null) {
|
||||
referrer = vreq.getHeader("Referer");
|
||||
}
|
||||
if (referrer == null) {
|
||||
referrer = "/";
|
||||
}
|
||||
return referrer;
|
||||
}
|
||||
|
||||
private void setMaxFileSize() {
|
||||
ConfigurationProperties config = ConfigurationProperties.getBean(getServletContext());
|
||||
String configFileSize = config.getProperty(CONFIG_MAX_FILE_SIZE, DEFAULT_FILE_SIZE.toString());
|
||||
try {
|
||||
maxFileSize = Long.parseLong(configFileSize);
|
||||
} catch (NumberFormatException e) {
|
||||
log.error("maxFileSize parsing failed");
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
static class FileUploadException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final Object[] parameters;
|
||||
|
||||
FileUploadException(String message, Object... parameters) {
|
||||
super(message);
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public String formatMessage(HttpServletRequest req) {
|
||||
return I18n.text(req, getMessage(), parameters);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -234,6 +234,9 @@ public class VitroVocabulary {
|
|||
public static final String IND_MAIN_IMAGE = VITRO_PUBLIC + "mainImage";
|
||||
public static final String IND_IMAGE = VITRO_PUBLIC + "image";
|
||||
|
||||
public static final String STORED_FILE = VITRO_PUBLIC + "storedFile";
|
||||
public static final String PUBLIC_FILENAME = VITRO_PUBLIC + "publicFilename";
|
||||
|
||||
// =============== Date Time with Precision vocabulary ===============
|
||||
private static final String DATETIME_NS = "http://vivoweb.org/ontology/core#";
|
||||
|
||||
|
|
|
@ -253,5 +253,21 @@ public class UploadedFileHelper {
|
|||
}
|
||||
return !stmts.isEmpty();
|
||||
}
|
||||
|
||||
public void removeUploadedFile(String subjectUri, String predicateUri, String fileUri) {
|
||||
FileInfo fileInfo = FileInfo.instanceFromSurrogateUri(wadf, fileUri);
|
||||
objectPropertyStatementDao
|
||||
.deleteObjectPropertyStatement(new ObjectPropertyStatementImpl(subjectUri, predicateUri, fileUri));
|
||||
deleteIfNotReferenced(fileInfo);
|
||||
}
|
||||
|
||||
public void attachFileToSubject(FileInfo fileInfo, String subjectUri, String predicateUri) {
|
||||
objectPropertyStatementDao
|
||||
.insertNewObjectPropertyStatement(new ObjectPropertyStatementImpl(subjectUri, predicateUri, fileInfo.getUri()));
|
||||
}
|
||||
|
||||
public void setPublicFileName(FileInfo fileInfo, String uploadedFileName) {
|
||||
dataPropertyStatementDao.insertNewDataPropertyStatement(
|
||||
new DataPropertyStatementImpl(fileInfo.getUri(), VitroVocabulary.PUBLIC_FILENAME, uploadedFileName));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,10 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
|
|||
if (VitroVocabulary.IND_MAIN_IMAGE.equals(property.getURI())) {
|
||||
return ObjectPropertyTemplateModel.getImageUploadUrl(subjectUri, "delete");
|
||||
}
|
||||
//If object is a File but not associated with main image
|
||||
if (ObjectPropertyTemplateModel.isFileStoreProperty(property)) {
|
||||
return ObjectPropertyTemplateModel.getDeleteFileUrl(subjectUri, property.getURI(), objectUri);
|
||||
}
|
||||
|
||||
ParamMap params = new ParamMap(
|
||||
"subjectUri", subjectUri,
|
||||
|
@ -109,6 +113,10 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
|
|||
if (VitroVocabulary.IND_MAIN_IMAGE.equals(property.getURI())) {
|
||||
return ObjectPropertyTemplateModel.getImageUploadUrl(subjectUri, "edit");
|
||||
}
|
||||
if (ObjectPropertyTemplateModel.isFileStoreProperty(property)) {
|
||||
//Disable file editing
|
||||
return "";
|
||||
}
|
||||
|
||||
ParamMap params = new ParamMap(
|
||||
"subjectUri", subjectUri,
|
||||
|
|
|
@ -39,6 +39,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
|||
private static final String TYPE = "object";
|
||||
private static final String EDIT_PATH = "editRequestDispatch";
|
||||
private static final String IMAGE_UPLOAD_PATH = "/uploadImages";
|
||||
private static final String FILE_UPLOAD_PATH = "/uploadFile";
|
||||
|
||||
private static final String END_DATE_TIME_VARIABLE = "dateTimeEnd";
|
||||
private static final Pattern ORDER_BY_END_DATE_TIME_PATTERN =
|
||||
|
@ -131,6 +132,8 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
|||
|
||||
if (propertyUri.equals(VitroVocabulary.IND_MAIN_IMAGE)) {
|
||||
addUrl = getImageUploadUrl(subjectUri, "add");
|
||||
} else if (isFileStoreProperty(property)) {
|
||||
addUrl = getFileUploadUrl(subjectUri,property.getURI());
|
||||
} else {
|
||||
ParamMap params = new ParamMap(
|
||||
"subjectUri", subjectUri,
|
||||
|
@ -149,7 +152,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Pull this into a protected method so we can stub it out in the unit tests.
|
||||
* Other options:
|
||||
* 1) receive a TemplateLoader into the constructor of ObjectPropertyTemplateModel,
|
||||
|
@ -378,4 +381,20 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
|||
|
||||
public abstract boolean isCollatedBySubclass();
|
||||
|
||||
|
||||
protected static boolean isFileStoreProperty(Property property) {
|
||||
return property.getRangeVClassURI() != null && property.getRangeVClassURI().equals(VitroVocabulary.FS_FILE_CLASS);
|
||||
}
|
||||
|
||||
public static String getDeleteFileUrl(String subjectUri, String predicateUri, String objectUri) {
|
||||
ParamMap params = new ParamMap("subjectUri", subjectUri, "predicateUri", predicateUri, "fileUri", objectUri,
|
||||
"action", "delete");
|
||||
return UrlBuilder.getUrl(FILE_UPLOAD_PATH, params);
|
||||
}
|
||||
|
||||
private static String getFileUploadUrl(String subjectUri, String predicateUri) {
|
||||
ParamMap params = new ParamMap("subjectUri", subjectUri, "predicateUri", predicateUri, "action", "upload");
|
||||
return UrlBuilder.getUrl(FILE_UPLOAD_PATH, params);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
5
dependencies/pom.xml
vendored
5
dependencies/pom.xml
vendored
|
@ -256,6 +256,11 @@
|
|||
<artifactId>taglibs-standard-impl</artifactId>
|
||||
<version>1.2.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tika</groupId>
|
||||
<artifactId>tika-core</artifactId>
|
||||
<version>2.1.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
|
|
|
@ -185,3 +185,8 @@ proxy.eligibleTypeList = http://www.w3.org/2002/07/owl#Thing
|
|||
# Vitro does not contain restricted data that should not be shared with others.
|
||||
#
|
||||
# tpf.activeFlag = true
|
||||
#
|
||||
# File upload file size in bytes. By default 1048576 bytes (10Mb)
|
||||
#fileUpload.maxFileSize = 1048576
|
||||
#comma separated list of mime types allowed for upload
|
||||
#fileUpload.allowedMIMETypes = image/png, application/pdf
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<http://vitro.mannlib.cornell.edu/ns/vitro/public#storedFile> <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#listViewConfigFile> "listViewConfig-storedFile.xml" .
|
|
@ -43,6 +43,11 @@
|
|||
<rdfs:range rdf:resource="&xsd;string"/>
|
||||
</owl:DatatypeProperty>
|
||||
|
||||
<owl:DatatypeProperty rdf:about="#publicFilename">
|
||||
<rdfs:domain><owl:Class rdf:about="#File"/></rdfs:domain>
|
||||
<rdfs:range rdf:resource="&xsd;string"/>
|
||||
</owl:DatatypeProperty>
|
||||
|
||||
<owl:DatatypeProperty rdf:about="#attribution">
|
||||
<rdfs:domain><owl:Class rdf:about="#File"/></rdfs:domain>
|
||||
<rdfs:range rdf:resource="&xsd;string"/>
|
||||
|
@ -67,6 +72,10 @@
|
|||
<rdfs:range><owl:Class rdf:about="#File"/></rdfs:range>
|
||||
</owl:ObjectProperty>
|
||||
|
||||
<owl:ObjectProperty rdf:about="#storedFile">
|
||||
<rdfs:range><owl:Class rdf:about="#File"/></rdfs:range>
|
||||
</owl:ObjectProperty>
|
||||
|
||||
<owl:ObjectProperty rdf:about="#image">
|
||||
<rdfs:range><owl:Class rdf:about="#File"/></rdfs:range>
|
||||
</owl:ObjectProperty>
|
||||
|
|
44
webapp/src/main/webapp/config/listViewConfig-storedFile.xml
Normal file
44
webapp/src/main/webapp/config/listViewConfig-storedFile.xml
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!-- $This file is distributed under the terms of the license in LICENSE$ -->
|
||||
|
||||
<!-- Default list view config file for object properties
|
||||
|
||||
See guidelines at https://wiki.duraspace.org/x/eYXVAw -->
|
||||
|
||||
<list-view-config>
|
||||
<query-select>
|
||||
|
||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||
PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#>
|
||||
PREFIX vitro-public: <http://vitro.mannlib.cornell.edu/ns/vitro/public#>
|
||||
|
||||
SELECT <collated> ?subclass </collated>
|
||||
?object
|
||||
?filename
|
||||
?publicFilename
|
||||
?localName
|
||||
?url
|
||||
WHERE {
|
||||
?subject ?property ?object .
|
||||
LET (?localName := REPLACE(STR(?object),"^.*(#)(.*)$", "$2"))
|
||||
?object vitro-public:filename ?filename .
|
||||
?object vitro-public:publicFilename ?publicFilename .
|
||||
?object vitro-public:downloadLocation ?url .
|
||||
|
||||
<collated>
|
||||
OPTIONAL {
|
||||
<precise-subquery>?subject ?property ?object .</precise-subquery>
|
||||
?object a ?subclass .
|
||||
# Require the subclasses retrieved to be in a classgroup, since others are not generally
|
||||
# for display. See vivo-dev-all thread titled "Internal Entity and mostSpecificType,"
|
||||
# Aug 9-10, 2011.
|
||||
# ?subclass vitro:inClassGroup ?classgroup
|
||||
}
|
||||
FILTER ( REPLACE(STR(?subclass),"^(.*)(#)(.*)$", "$1$2") != "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#" )
|
||||
</collated>
|
||||
|
||||
} ORDER BY <collated> ?subclass </collated> ASC( ?publicFilename ) ASC( ?localName )
|
||||
</query-select>
|
||||
|
||||
<template>storedFile-default.ftl</template>
|
||||
</list-view-config>
|
61
webapp/src/main/webapp/js/fileUpload/fileUploadUtils.js
Normal file
61
webapp/src/main/webapp/js/fileUpload/fileUploadUtils.js
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* $This file is distributed under the terms of the license in LICENSE$ */
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
var xpath = "//attribute::href[contains(., '/uploadFile')]";
|
||||
var result = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
|
||||
var node = null;
|
||||
while (node = result.iterateNext()) {
|
||||
if(isDeleteUploadFile(node)){
|
||||
$(node.ownerElement).click(function(){
|
||||
var answer = confirm(i18n_confirmDeleteUploadedFile);
|
||||
return answer;
|
||||
});
|
||||
} else if (isUploadFile(node)){
|
||||
$(node.ownerElement).click(function(){
|
||||
uploadFileRequest(event.target);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function isDeleteUploadFile(node){
|
||||
var url = node.nodeValue;
|
||||
if (url.match("&action=delete")){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isUploadFile(node){
|
||||
var url = node.nodeValue;
|
||||
if (url.match("&action=upload")){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function uploadFileRequest(node){
|
||||
var aElement = node.parentElement;
|
||||
var form = document.createElement("form");
|
||||
form.setAttribute("method", "post");
|
||||
form.setAttribute("action", aElement.href);
|
||||
form.setAttribute("enctype","multipart/form-data");
|
||||
form.setAttribute("role","form");
|
||||
document.body.insertBefore(form, null);
|
||||
var inputFile = document.createElement("input");
|
||||
inputFile.type = "file";
|
||||
inputFile.name = "datafile";
|
||||
var inputId = "fileUploadInput" + Math.floor(Math.random() * 1000000);
|
||||
inputFile.setAttribute("id", inputId);
|
||||
inputFile.setAttribute("style", "display:none;");
|
||||
form.insertBefore(inputFile, null);
|
||||
inputFile.click();
|
||||
inputFile.addEventListener("change", onFileSelect);
|
||||
}
|
||||
|
||||
function onFileSelect(e) {
|
||||
e.target.parentElement.submit();
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<#-- $This file is distributed under the terms of the license in LICENSE$ -->
|
||||
|
||||
|
||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/fileUpload/fileUploadUtils.js"></script>')}
|
||||
|
||||
<#assign i18n = i18n() >
|
||||
|
||||
<section id="fileploadContainer" role="region">
|
||||
<h2>${i18n.file_upload_heading}</h2>
|
||||
|
||||
<#if errorMessage??>
|
||||
<section id="error-alert" role="alert"><img src="${urls.images}/iconAlert.png" alt="${i18n.alt_error_alert}" />
|
||||
<p>${errorMessage}</p>
|
||||
</section>
|
||||
</#if>
|
||||
<#if action?? && action == "upload" >
|
||||
<form id="fileUploadForm" action="${formAction}" enctype="multipart/form-data" method="post" role="form">
|
||||
<label>${i18n.upload_files_supported_types}
|
||||
<#if supportedTypes??>
|
||||
<span>${supportedTypes}</span></label>
|
||||
</#if>
|
||||
<#if supportedMIMETypes??>
|
||||
<span>MIME Types: ${supportedMIMETypes}</span></label>
|
||||
</#if>
|
||||
<input id="datafile" type="file" name="datafile" size="30" />
|
||||
<p class="note">${i18n.maximum_file_size(maxFileSize)}</p>
|
||||
<input class="submit" type="submit" value="${i18n.submit_file_upload}"/>
|
||||
|
||||
<span class="or"> ${i18n.or} <a class="cancel" href="${referrer}" title="${i18n.cancel_title}">${i18n.cancel_link}</a></span>
|
||||
</form>
|
||||
</#if>
|
||||
</section>
|
|
@ -106,9 +106,11 @@ ${headScripts.add('<script type="text/javascript" src="${urls.base}/js/jquery_pl
|
|||
'<script type="text/javascript" src="${urls.base}/js/tiny_mce/tiny_mce.js"></script>')}
|
||||
|
||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/imageUpload/imageUploadUtils.js"></script>',
|
||||
'<script type="text/javascript" src="${urls.base}/js/fileUpload/fileUploadUtils.js"></script>',
|
||||
'<script type="text/javascript" src="${urls.base}/js/individual/moreLessController.js"></script>',
|
||||
'<script type="text/javascript" src="${urls.base}/js/individual/individualUriRdf.js"></script>')}
|
||||
|
||||
<script type="text/javascript">
|
||||
i18n_confirmDelete = "${i18n().confirm_delete?js_string}";
|
||||
i18n_confirmDeleteUploadedFile = "${i18n().confirm_delete_uploaded_file?js_string}";
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
<#-- $This file is distributed under the terms of the license in LICENSE$ -->
|
||||
|
||||
<#-- Default object property statement template.
|
||||
|
||||
This template must be self-contained and not rely on other variables set for the individual page, because it
|
||||
is also used to generate the property statement during a deletion.
|
||||
-->
|
||||
<@showFiles statement individual />
|
||||
|
||||
<#macro showFiles statement individual>
|
||||
<a download="${statement.publicFilename}" title="${i18n().name}" href="${profileUrl(statement.url)}" >${statement.publicFilename}</a>
|
||||
</#macro>
|
Loading…
Add table
Reference in a new issue