Adding new image upload services for Data URLs (Webcam integration)

This commit is contained in:
Vishwas Babu AJ
2012-11-09 19:25:03 +05:30
parent e0a7231f13
commit 0d33fcf118
6 changed files with 206 additions and 27 deletions
@@ -35,6 +35,7 @@ import org.mifosng.platform.api.infrastructure.PortfolioApiJsonSerializerService
import org.mifosng.platform.client.service.ClientReadPlatformService;
import org.mifosng.platform.client.service.ClientWritePlatformService;
import org.mifosng.platform.common.ApplicationConstants;
import org.mifosng.platform.common.Base64EncodedImage;
import org.mifosng.platform.common.FileUtils;
import org.mifosng.platform.exceptions.ClientNotFoundException;
import org.mifosng.platform.exceptions.ImageNotFoundException;
@@ -325,6 +326,14 @@ public class ClientsApiResource {
return Response.ok().entity(identifier).build();
}
/** Upload images through multi-part form upload
* @param clientId
* @param fileSize
* @param inputStream
* @param fileDetails
* @param bodyPart
* @return
*/
@POST
@Path("{clientId}/image")
@Consumes({ MediaType.MULTIPART_FORM_DATA })
@@ -355,8 +364,33 @@ public class ClientsApiResource {
return Response.ok().entity(entityIdentifier).build();
}
/**Returns a base 64 encoded client image
/** Upload image as a Data URL (essentially a base64 encoded stream)
* @param clientId
* @param jsonRequestBody
* @return
*/
@POST
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response addNewClientImage(
@PathParam("clientId") final Long clientId,
final String jsonRequestBody) {
Base64EncodedImage base64EncodedImage = FileUtils
.extractImageFromDataURL(jsonRequestBody);
EntityIdentifier entityIdentifier = this.clientWritePlatformService
.saveOrUpdateClientImage(clientId, base64EncodedImage);
// return identifier of the client whose image was updated
return Response.ok().entity(entityIdentifier).build();
}
/**
* Returns a base 64 encoded client image
* @param clientId
* @return
*/
@@ -413,4 +447,25 @@ public class ClientsApiResource {
this.clientWritePlatformService.deleteClientImage(clientId);
return Response.ok(new EntityIdentifier(clientId)).build();
}
/**
* This method is added only for consistency with other URL patterns
* and for maintaining consistency of usage of the HTTP "verb"
* at the client side
*
* Upload image as a Data URL (essentially a base64 encoded stream)
* @param clientId
* @param jsonRequestBody
* @return
*/
@PUT
@Path("{clientId}/image")
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_JSON })
public Response updateClientImage(
@PathParam("clientId") final Long clientId,
final String jsonRequestBody) {
return addNewClientImage(clientId, jsonRequestBody);
}
}
@@ -6,6 +6,7 @@ import org.mifosng.platform.api.commands.ClientCommand;
import org.mifosng.platform.api.commands.ClientIdentifierCommand;
import org.mifosng.platform.api.commands.NoteCommand;
import org.mifosng.platform.api.data.EntityIdentifier;
import org.mifosng.platform.common.Base64EncodedImage;
import org.springframework.security.access.prepost.PreAuthorize;
public interface ClientWritePlatformService {
@@ -19,6 +20,9 @@ public interface ClientWritePlatformService {
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
EntityIdentifier saveOrUpdateClientImage(Long clientId, String imageName, InputStream inputStream);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
EntityIdentifier saveOrUpdateClientImage(Long clientId, Base64EncodedImage encodedImage);
@PreAuthorize(value = "hasAnyRole('PORTFOLIO_MANAGEMENT_SUPER_USER_ROLE')")
EntityIdentifier deleteClientImage(Long clientId);
@@ -16,6 +16,7 @@ import org.mifosng.platform.client.domain.ClientRepository;
import org.mifosng.platform.client.domain.Note;
import org.mifosng.platform.client.domain.NoteRepository;
import org.mifosng.platform.common.ApplicationConstants;
import org.mifosng.platform.common.Base64EncodedImage;
import org.mifosng.platform.common.FileUtils;
import org.mifosng.platform.exceptions.ClientIdentifierNotFoundException;
import org.mifosng.platform.exceptions.ClientNotFoundException;
@@ -333,34 +334,14 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
String imageName, InputStream inputStream) {
try {
final Client client = this.clientRepository.findOne(clientId);
if (client == null || client.isDeleted()) {
throw new ClientNotFoundException(clientId);
}
String imageUploadLocation = FileUtils
.generateImageParentDirectory(
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
clientId);
// delete previous image from the file system
if (StringUtils.isNotEmpty(client.getImageKey())) {
FileUtils.deleteImage(
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
clientId, client.getImageKey());
}
/** Recursively create the directory if it does not exist **/
if (!new File(imageUploadLocation).isDirectory()) {
new File(imageUploadLocation).mkdirs();
}
String imageUploadLocation = setupForClientImageUpdate(clientId,
client);
String imageLocation = FileUtils.saveToFileSystem(inputStream,
imageUploadLocation, imageName);
client.setImageKey(imageLocation);
this.clientRepository.save(client);
return new EntityIdentifier(clientId);
return updateClientImage(clientId, client, imageLocation);
} catch (IOException ioe) {
logger.error(ioe.getMessage(), ioe);
throw new DocumentManagementException(imageName);
@@ -380,8 +361,66 @@ public class ClientWritePlatformServiceJpaRepositoryImpl implements ClientWriteP
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
clientId, client.getImageKey());
}
client.setImageKey(null);
return updateClientImage(clientId, client, null);
}
@Override
public EntityIdentifier saveOrUpdateClientImage(Long clientId,
Base64EncodedImage encodedImage) {
try {
final Client client = this.clientRepository.findOne(clientId);
String imageUploadLocation = setupForClientImageUpdate(clientId,
client);
String imageLocation = FileUtils.saveToFileSystem(encodedImage, imageUploadLocation, "image");
return updateClientImage(clientId, client, imageLocation);
} catch (IOException ioe) {
logger.error(ioe.getMessage(), ioe);
throw new DocumentManagementException("image");
}
}
/**
* @param clientId
* @param client
* @return
*/
private String setupForClientImageUpdate(Long clientId, final Client client) {
if (client == null || client.isDeleted()) {
throw new ClientNotFoundException(clientId);
}
String imageUploadLocation = FileUtils
.generateImageParentDirectory(
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
clientId);
// delete previous image from the file system
if (StringUtils.isNotEmpty(client.getImageKey())) {
FileUtils.deleteImage(
ApplicationConstants.IMAGE_MANAGEMENT_ENTITY.CLIENTS,
clientId, client.getImageKey());
}
/** Recursively create the directory if it does not exist **/
if (!new File(imageUploadLocation).isDirectory()) {
new File(imageUploadLocation).mkdirs();
}
return imageUploadLocation;
}
/**
* @param clientId
* @param client
* @param imageLocation
* @return
*/
private EntityIdentifier updateClientImage(Long clientId,
final Client client, String imageLocation) {
client.setImageKey(imageLocation);
this.clientRepository.save(client);
return new EntityIdentifier(clientId);
}
@@ -0,0 +1,21 @@
package org.mifosng.platform.common;
public class Base64EncodedImage {
private final String base64EncodedString;
private final String fileExtension;
public Base64EncodedImage(String base64EncodedString, String fileExtension) {
this.base64EncodedString = base64EncodedString;
this.fileExtension = fileExtension;
}
public String getBase64EncodedString() {
return base64EncodedString;
}
public String getFileExtension() {
return fileExtension;
}
}
@@ -11,12 +11,15 @@ import java.util.Random;
import org.mifosng.platform.api.data.ApiParameterError;
import org.mifosng.platform.exceptions.DocumentManagementException;
import org.mifosng.platform.exceptions.ImageDataURLNotValidException;
import org.mifosng.platform.exceptions.ImageUploadException;
import org.mifosng.platform.exceptions.PlatformApiDataValidationException;
import org.mifosng.platform.infrastructure.ThreadLocalContextUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.lowagie.text.pdf.codec.Base64;
public class FileUtils {
private final static Logger logger = LoggerFactory
@@ -107,6 +110,25 @@ public class FileUtils {
out.close();
return fileLocation;
}
/**
* @param base64EncodedImage
* @param uploadedFileLocation
* @param fileName
* @return
* @throws IOException
*/
public static String saveToFileSystem(Base64EncodedImage base64EncodedImage,
String uploadedFileLocation, String fileName) throws IOException {
String fileLocation = uploadedFileLocation + File.separator + fileName + base64EncodedImage.getFileExtension();
OutputStream out = new FileOutputStream(new File(fileLocation));
byte[] imgBytes = Base64.decode(base64EncodedImage.getBase64EncodedString());
out.write(imgBytes);
out.flush();
out.close();
return fileLocation;
}
/**
* @param fileSize
@@ -137,8 +159,35 @@ public class FileUtils {
throw new ImageUploadException();
}
}
/**
* Extracts Image from a Data URL
*
* @param mimeType
*/
public static Base64EncodedImage extractImageFromDataURL(String dataURL) {
String fileExtension = "";
String base64EncodedString = null;
String gifDataURLSnippet = "data:image/gif;base64,";
String pngDataURLSnippet = "data:image/png;base64,";
String jpegDataURLSnippet = "data:image/jpeg;base64,";
if (dataURL.contains(gifDataURLSnippet)) {
base64EncodedString = dataURL.replaceAll(gifDataURLSnippet, "");
fileExtension = ".gif";
} else if (dataURL.contains(pngDataURLSnippet)) {
base64EncodedString = dataURL.replaceAll(pngDataURLSnippet, "");
fileExtension = ".png";
} else if (dataURL.contains(jpegDataURLSnippet)) {
base64EncodedString = dataURL.replaceAll(jpegDataURLSnippet, "");
fileExtension = ".jpeg";
} else {
throw new ImageDataURLNotValidException();
}
return new Base64EncodedImage(base64EncodedString, fileExtension);
}
public static void validateClientImageNotEmpty(String imageFileName) {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (imageFileName == null) {
@@ -0,0 +1,11 @@
package org.mifosng.platform.exceptions;
public class ImageDataURLNotValidException extends
AbstractPlatformDomainRuleException {
public ImageDataURLNotValidException() {
super("error.msg.dataURL.save",
"Only GIF, PNG and JPEG Data URL's are allowed");
}
}