Commit 0efa2385 authored by Martin Lowe's avatar Martin Lowe 🇨🇦
Browse files

#445 - Fix EPS compression, save source of compressed images

parent 95e8c912
...@@ -13,7 +13,7 @@ public interface ImageStoreFormat { ...@@ -13,7 +13,7 @@ public interface ImageStoreFormat {
String getName(); String getName();
public enum ImageStoreFormats implements ImageStoreFormat { public enum ImageStoreFormats implements ImageStoreFormat {
SMALL, LARGE, PRINT, WEB; SMALL, LARGE, PRINT, WEB, WEB_SRC;
@Override @Override
public String getName() { public String getName() {
......
...@@ -49,7 +49,8 @@ public interface ImageStoreService { ...@@ -49,7 +49,8 @@ public interface ImageStoreService {
* @param format the name of the format to write the image for * @param format the name of the format to write the image for
* @return absolute path to access the live image * @return absolute path to access the live image
*/ */
String writeImage(Supplier<byte[]> imageBytes, String organization, String mimeType, Optional<ImageStoreFormat> format); String writeImage(Supplier<byte[]> imageBytes, String organization, String mimeType,
Optional<ImageStoreFormat> format);
/** /**
* Remove images associated with the given organization. This should clear all images that exist for the * Remove images associated with the given organization. This should clear all images that exist for the
...@@ -73,17 +74,33 @@ public interface ImageStoreService { ...@@ -73,17 +74,33 @@ public interface ImageStoreService {
String webRoot(); String webRoot();
@WithDefault("1000000")
long maxSizeInBytes();
@WithDefault("") @WithDefault("")
String defaultImageUrl(); String defaultImageUrl();
MaxSizeInBytes maxSizeInBytes();
Compression compression(); Compression compression();
@WithDefault("false") @WithDefault("false")
boolean persistToDb(); boolean persistToDb();
/**
* Contains the properties regarding max size of saved assets
*
* @author Martin Lowe
*
*/
interface MaxSizeInBytes {
@WithDefault("1000000")
long web();
@WithDefault("64000")
long webPostCompression();
@WithDefault("10000000")
long print();
}
/** /**
* Represents compression configuration settings. * Represents compression configuration settings.
* *
...@@ -93,10 +110,10 @@ public interface ImageStoreService { ...@@ -93,10 +110,10 @@ public interface ImageStoreService {
interface Compression { interface Compression {
@WithDefault("true") @WithDefault("true")
boolean enabled(); boolean enabled();
@WithDefault("200") @WithDefault("200")
int maxDimension(); int maxDimension();
@WithDefault("0.80f") @WithDefault("0.80f")
@Max(1) @Max(1)
float factor(); float factor();
......
...@@ -51,6 +51,7 @@ import org.eclipsefoundation.persistence.model.RDBMSQuery; ...@@ -51,6 +51,7 @@ import org.eclipsefoundation.persistence.model.RDBMSQuery;
import org.eclipsefoundation.persistence.service.FilterService; import org.eclipsefoundation.persistence.service.FilterService;
import org.eclipsefoundation.react.helper.ImageFileHelper; import org.eclipsefoundation.react.helper.ImageFileHelper;
import org.eclipsefoundation.react.namespace.ImageStoreFormat; import org.eclipsefoundation.react.namespace.ImageStoreFormat;
import org.eclipsefoundation.react.namespace.ImageStoreFormat.ImageStoreFormats;
import org.eclipsefoundation.react.service.ImageStoreService; import org.eclipsefoundation.react.service.ImageStoreService;
import org.imgscalr.Scalr; import org.imgscalr.Scalr;
import org.jboss.resteasy.specimpl.MultivaluedMapImpl; import org.jboss.resteasy.specimpl.MultivaluedMapImpl;
...@@ -153,20 +154,39 @@ public class DefaultImageStoreService implements ImageStoreService { ...@@ -153,20 +154,39 @@ public class DefaultImageStoreService implements ImageStoreService {
// cannot provide image, return null // cannot provide image, return null
return null; return null;
} }
// compress image and then compare max size if (format.isPresent() && format.get().equals(ImageStoreFormats.PRINT)) {
byte[] compressedImage = compress(bytes, mimeType); if (bytes.length > config.maxSizeInBytes().print()) {
if (compressedImage.length > config.maxSizeInBytes() && (!Files.exists(p) throw new BadRequestException("Passed image is larger than allowed size of '"
|| !approximatelyMatch((long) compressedImage.length, attrView.readAttributes().size(), 1000))) { + config.maxSizeInBytes().print() + "' bytes");
throw new BadRequestException( }
"Passed image is larger than allowed size of '" + config.maxSizeInBytes() + "' bytes"); // Any print files should not attempt compression (as they are meant to be big)
} return getWebUrl(Files.write(p, bytes));
// if enabled, update the EclipseDB on logo update when image name is numeric } else {
// max size check is related to max blob size of 64kb if (bytes.length > config.maxSizeInBytes().web()) {
// TODO remove once the Drupal API references this API as this will no longer be needed then throw new BadRequestException("Passed image is larger than allowed size of '"
handleDBPersist(fileName, compressedImage, mimeType, format); + config.maxSizeInBytes().web() + "' bytes");
}
// compress image and then compare max size
byte[] compressedImage = compress(bytes, mimeType);
if (compressedImage.length > config.maxSizeInBytes().webPostCompression()
&& (!Files.exists(p) || !approximatelyMatch((long) compressedImage.length,
attrView.readAttributes().size(), 1000))) {
throw new BadRequestException("Passed image is larger than allowed size of '"
+ config.maxSizeInBytes().webPostCompression() + "' bytes");
}
// if enabled, update the EclipseDB on logo update when image name is numeric
// max size check is related to max blob size of 64kb
// TODO remove once the Drupal API references this API as this will no longer be needed then
handleDBPersist(fileName, compressedImage, mimeType, format);
// write will create and overwrite file by default if it exists // write the orginal bytes to preserve source file in case of emergency
return getWebUrl(Files.write(p, compress(bytes, mimeType))); Files.write(imageStoreRoot.resolve(ImageFileHelper.getFileNameWithExtension(fileName,
Optional.of(ImageStoreFormats.WEB_SRC), mimeType)), bytes);
// write will create and overwrite file by default if it exists
return getWebUrl(Files.write(p, compressedImage));
}
} catch (IOException e) { } catch (IOException e) {
throw new ServerErrorException("Could not write image for organization " + fileName, throw new ServerErrorException("Could not write image for organization " + fileName,
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e); Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), e);
...@@ -229,8 +249,8 @@ public class DefaultImageStoreService implements ImageStoreService { ...@@ -229,8 +249,8 @@ public class DefaultImageStoreService implements ImageStoreService {
// get a ref to the given organization information object // get a ref to the given organization information object
MultivaluedMap<String, String> params = new MultivaluedMapImpl<>(); MultivaluedMap<String, String> params = new MultivaluedMapImpl<>();
params.add(DefaultUrlParameterNames.ID.getName(), fileName); params.add(DefaultUrlParameterNames.ID.getName(), fileName);
List<OrganizationInformation> infoRefs = dao List<OrganizationInformation> infoRefs = dao.get(
.get(new RDBMSQuery<>(new RequestWrapper(), filters.get(OrganizationInformation.class), params)); new RDBMSQuery<>(new RequestWrapper(), filters.get(OrganizationInformation.class), params));
// if ref doesn't exist, create one // if ref doesn't exist, create one
OrganizationInformation oi; OrganizationInformation oi;
if (infoRefs.isEmpty()) { if (infoRefs.isEmpty()) {
...@@ -247,7 +267,7 @@ public class DefaultImageStoreService implements ImageStoreService { ...@@ -247,7 +267,7 @@ public class DefaultImageStoreService implements ImageStoreService {
oi.setSmallMime(mimeType); oi.setSmallMime(mimeType);
dao.add(new RDBMSQuery<>(new RequestWrapper(), filters.get(OrganizationInformation.class)), dao.add(new RDBMSQuery<>(new RequestWrapper(), filters.get(OrganizationInformation.class)),
Arrays.asList(oi)); Arrays.asList(oi));
} }
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment