Also adds an output parameter to allow viewing images directly in the browser (values octet to download as an attachment, and inline_octet to view inline)

This commit is contained in:
blingdahl
2014-06-21 22:32:58 -07:00
committed by Vishwas Babu A J
parent c2c2f65c13
commit f9dfd409db
3 changed files with 116 additions and 23 deletions
@@ -16,6 +16,7 @@ import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
@@ -106,7 +107,10 @@ public class ImagesApiResource {
@GET
@Consumes({ MediaType.TEXT_PLAIN, MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.TEXT_PLAIN })
public String retrieveClientImage(@PathParam("clientId") final Long clientId) {
public Response retrieveClientImage(@PathParam("clientId") final Long clientId, @QueryParam("maxWidth") final Integer maxWidth,
@QueryParam("maxHeight") final Integer maxHeight, @QueryParam("output") final String output) {
if (output != null && (output.equals("octet") || output.equals("inline_octet"))) { return downloadClientImage(clientId, maxWidth,
maxHeight, output); }
this.context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE");
@@ -120,21 +124,23 @@ public class ImagesApiResource {
imageDataURISuffix = ContentRepositoryUtils.IMAGE_DATA_URI_SUFFIX.PNG.getValue();
}
final String clientImageAsBase64Text = imageDataURISuffix + Base64.encodeBytes(imageData.getContent());
return clientImageAsBase64Text;
final String clientImageAsBase64Text = imageDataURISuffix + Base64.encodeBytes(imageData.getContentOfSize(maxWidth, maxHeight));
return Response.ok(clientImageAsBase64Text).build();
}
@GET
@Consumes({ MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_OCTET_STREAM })
public Response downloadClientImage(@PathParam("clientId") final Long clientId) {
public Response downloadClientImage(@PathParam("clientId") final Long clientId, @QueryParam("maxWidth") final Integer maxWidth,
@QueryParam("maxHeight") final Integer maxHeight, @QueryParam("output") String output) {
this.context.authenticatedUser().validateHasReadPermission("CLIENTIMAGE");
final ImageData imageData = this.imageReadPlatformService.retrieveClientImage(clientId);
final ResponseBuilder response = Response.ok(imageData.getContent());
response.header("Content-Disposition", "attachment; filename=\"" + imageData.getEntityDisplayName() + IMAGE_FILE_EXTENSION.JPEG
+ "\"");
final ResponseBuilder response = Response.ok(imageData.getContentOfSize(maxWidth, maxHeight));
String dispositionType = "inline_octet".equals(output) ? "inline" : "attachment";
response.header("Content-Disposition", dispositionType + "; filename=\"" + imageData.getEntityDisplayName()
+ IMAGE_FILE_EXTENSION.JPEG + "\"");
// TODO: Need a better way of determining image type
@@ -28,6 +28,20 @@ public class ContentRepositoryUtils {
public String getValue() {
return this.value;
}
public static IMAGE_MIME_TYPE fromFileExtension(IMAGE_FILE_EXTENSION fileExtension) {
switch (fileExtension) {
case GIF:
return IMAGE_MIME_TYPE.GIF;
case JPG:
case JPEG:
return IMAGE_MIME_TYPE.JPEG;
case PNG:
return IMAGE_MIME_TYPE.PNG;
default:
throw new IllegalArgumentException();
}
}
}
public static enum IMAGE_FILE_EXTENSION {
@@ -42,6 +56,23 @@ public class ContentRepositoryUtils {
public String getValue() {
return this.value;
}
public String getValueWithoutDot() {
return this.value.substring(1);
}
public IMAGE_FILE_EXTENSION getFileExtension() {
switch (this) {
case GIF:
return IMAGE_FILE_EXTENSION.GIF;
case JPEG:
return IMAGE_FILE_EXTENSION.JPEG;
case PNG:
return IMAGE_FILE_EXTENSION.PNG;
default:
throw new IllegalArgumentException();
}
}
}
public static enum IMAGE_DATA_URI_SUFFIX {
@@ -1,9 +1,17 @@
package org.mifosplatform.infrastructure.documentmanagement.data;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.imageio.ImageIO;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.util.IOUtils;
@@ -19,7 +27,7 @@ public class ImageData {
private final String entityDisplayName;
private File file;
private String contentType;
private ContentRepositoryUtils.IMAGE_FILE_EXTENSION fileExtension;
private InputStream inputStream;
public ImageData(final Long imageId, final String location, final Integer storageType, final String entityDisplayName) {
@@ -43,23 +51,76 @@ public class ImageData {
}
}
private String setImageContentType() {
String contentType = ContentRepositoryUtils.IMAGE_MIME_TYPE.JPEG.getValue();
public byte[] resizeImage(InputStream in, int maxWidth, int maxHeight) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
resizeImage(in, out, maxWidth, maxHeight);
return out.toByteArray();
}
if (this.file != null) {
final String fileName = this.file.getName();
public void resizeImage(InputStream in, OutputStream out, int maxWidth, int maxHeight) throws IOException {
if (StringUtils.endsWith(fileName, ContentRepositoryUtils.IMAGE_FILE_EXTENSION.GIF.getValue())) {
contentType = ContentRepositoryUtils.IMAGE_MIME_TYPE.GIF.getValue();
} else if (StringUtils.endsWith(fileName, ContentRepositoryUtils.IMAGE_FILE_EXTENSION.PNG.getValue())) {
contentType = ContentRepositoryUtils.IMAGE_MIME_TYPE.PNG.getValue();
BufferedImage src = ImageIO.read(in);
if (src.getWidth() <= maxWidth && src.getHeight() <= maxHeight) {
out.write(getContent());
return;
}
float widthRatio = (float) src.getWidth() / maxWidth;
float heightRatio = (float) src.getHeight() / maxHeight;
float scaleRatio = widthRatio > heightRatio ? widthRatio : heightRatio;
// TODO(lindahl): Improve compressed image quality (perhaps quality
// ratio)
int newWidth = (int) (src.getWidth() / scaleRatio);
int newHeight = (int) (src.getHeight() / scaleRatio);
int colorModel = fileExtension == ContentRepositoryUtils.IMAGE_FILE_EXTENSION.JPEG ? BufferedImage.TYPE_INT_RGB
: BufferedImage.TYPE_INT_ARGB;
BufferedImage target = new BufferedImage(newWidth, newHeight, colorModel);
Graphics2D g = target.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(src, 0, 0, newWidth, newHeight, Color.BLACK, null);
g.dispose();
ImageIO.write(target, fileExtension != null ? fileExtension.getValueWithoutDot() : "jpeg", out);
}
public byte[] getContentOfSize(Integer maxWidth, Integer maxHeight) {
if (maxWidth == null && maxHeight == null) { return getContent(); }
FileInputStream fis = null;
try {
fis = new FileInputStream(this.file);
byte[] out = resizeImage(fis, maxWidth != null ? maxWidth : Integer.MAX_VALUE, maxHeight != null ? maxHeight
: Integer.MAX_VALUE);
return out;
} catch (IOException ex) {
return null;
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException ex) {}
}
}
return contentType;
}
private void setImageContentType(String filename) {
fileExtension = ContentRepositoryUtils.IMAGE_FILE_EXTENSION.JPEG;
if (StringUtils.endsWith(filename.toLowerCase(), ContentRepositoryUtils.IMAGE_FILE_EXTENSION.GIF.getValue())) {
fileExtension = ContentRepositoryUtils.IMAGE_FILE_EXTENSION.GIF;
} else if (StringUtils.endsWith(filename, ContentRepositoryUtils.IMAGE_FILE_EXTENSION.PNG.getValue())) {
fileExtension = ContentRepositoryUtils.IMAGE_FILE_EXTENSION.PNG;
}
}
public void updateContent(final File file) {
this.file = file;
if (this.file != null) {
setImageContentType(this.file.getName());
}
}
public String contentType() {
return this.contentType;
return ContentRepositoryUtils.IMAGE_MIME_TYPE.fromFileExtension(this.fileExtension).getValue();
}
public StorageType storageType() {
@@ -78,11 +139,6 @@ public class ImageData {
this.inputStream = objectContent;
}
public void updateContent(final File file) {
this.file = file;
setImageContentType();
}
public String getEntityDisplayName() {
return this.entityDisplayName;
}