-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0653445
commit 8d14efc
Showing
9 changed files
with
139 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
src/main/java/app/fyreplace/api/exceptions/RequestEntityTooLargeException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package app.fyreplace.api.exceptions; | ||
|
||
import jakarta.ws.rs.ClientErrorException; | ||
import jakarta.ws.rs.core.Response; | ||
|
||
public class RequestEntityTooLargeException extends ClientErrorException { | ||
public RequestEntityTooLargeException() { | ||
super(Response.Status.REQUEST_ENTITY_TOO_LARGE); | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
src/main/java/app/fyreplace/api/services/ImageService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package app.fyreplace.api.services; | ||
|
||
import app.fyreplace.api.exceptions.RequestEntityTooLargeException; | ||
import app.fyreplace.api.exceptions.UnsupportedMediaTypeException; | ||
import app.fyreplace.api.services.mimetype.KnownFileType; | ||
import io.quarkus.runtime.configuration.MemorySize; | ||
import jakarta.enterprise.context.ApplicationScoped; | ||
import java.awt.image.BufferedImage; | ||
import java.io.ByteArrayInputStream; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.util.Arrays; | ||
import java.util.NoSuchElementException; | ||
import javax.imageio.ImageIO; | ||
import javax.imageio.ImageReader; | ||
import org.eclipse.microprofile.config.inject.ConfigProperty; | ||
|
||
@ApplicationScoped | ||
public final class ImageService { | ||
@ConfigProperty(name = "app.storage.limits.max-size") | ||
MemorySize fileMaxSize; | ||
|
||
public String getMimeType(final byte[] data) throws IOException { | ||
final var reader = getFirstValidReader(data); | ||
final var format = reader.getFormatName().toUpperCase(); | ||
|
||
try { | ||
return Arrays.stream(KnownFileType.values()) | ||
.filter(m -> m.name().equals(format)) | ||
.findFirst() | ||
.orElseThrow() | ||
.mime; | ||
} catch (final NoSuchElementException ignored) { | ||
throw new IOException(); | ||
} | ||
} | ||
|
||
public String getExtension(final byte[] data) { | ||
try { | ||
final var mime = getMimeType(data); | ||
return Arrays.stream(KnownFileType.values()) | ||
.filter(m -> m.mime.equals(mime)) | ||
.findFirst() | ||
.orElseThrow() | ||
.name() | ||
.toLowerCase(); | ||
} catch (final IOException | NoSuchElementException e) { | ||
return "unknown"; | ||
} | ||
} | ||
|
||
public void validate(final byte[] data) throws UnsupportedMediaTypeException { | ||
try { | ||
final var mimeType = getMimeType(data); | ||
|
||
if (Arrays.stream(KnownFileType.values()).noneMatch(m -> m.mime.equals(mimeType))) { | ||
throw new UnsupportedMediaTypeException(); | ||
} | ||
} catch (final IOException e) { | ||
throw new UnsupportedMediaTypeException(); | ||
} | ||
} | ||
|
||
public byte[] shrink(final byte[] data) throws IOException { | ||
final var softMaxSize = fileMaxSize.asLongValue(); | ||
|
||
if (data.length <= softMaxSize) { | ||
return data; | ||
} | ||
|
||
final var scaleFactor = Math.sqrt((double) softMaxSize / data.length); | ||
final var reader = getFirstValidReader(data); | ||
final var inputImage = ImageIO.read(new ByteArrayInputStream(data)); | ||
final var width = inputImage.getWidth() * scaleFactor; | ||
final var height = inputImage.getHeight() * scaleFactor; | ||
final var scaledImage = inputImage.getScaledInstance((int) width, (int) height, BufferedImage.SCALE_SMOOTH); | ||
final var outputImage = new BufferedImage((int) width, (int) height, inputImage.getType()); | ||
outputImage.getGraphics().drawImage(scaledImage, 0, 0, null); | ||
final var outputStream = new ByteArrayOutputStream(); | ||
ImageIO.write(outputImage, reader.getFormatName(), outputStream); | ||
final var outputData = outputStream.toByteArray(); | ||
|
||
if (outputData.length > softMaxSize * 1.5) { | ||
throw new RequestEntityTooLargeException(); | ||
} | ||
|
||
return outputData; | ||
} | ||
|
||
private ImageReader getFirstValidReader(final byte[] data) throws IOException { | ||
final var input = ImageIO.createImageInputStream(new ByteArrayInputStream(data)); | ||
final var readers = ImageIO.getImageReaders(input); | ||
|
||
while (readers.hasNext()) { | ||
final var reader = readers.next(); | ||
final var format = reader.getFormatName().toUpperCase(); | ||
|
||
if (Arrays.stream(KnownFileType.values()).anyMatch(m -> m.name().equals(format))) { | ||
return reader; | ||
} | ||
} | ||
|
||
throw new IOException(); | ||
} | ||
} |
60 changes: 0 additions & 60 deletions
60
src/main/java/app/fyreplace/api/services/MimeTypeService.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters