Adding new image upload services for Data URLs (Webcam integration)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
+4
@@ -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);
|
||||
|
||||
|
||||
+63
-24
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+21
@@ -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) {
|
||||
|
||||
Executable
+11
@@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user