Add picture format control.

This commit is contained in:
Florian THIERRY
2024-03-14 09:24:19 +01:00
parent 0b00f9b0aa
commit a872a9fe33
11 changed files with 132 additions and 6 deletions

View File

@@ -2,6 +2,7 @@ package org.codiki.exposition.configuration;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.FORBIDDEN;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;
import static org.springframework.http.HttpStatus.NOT_FOUND;
import static org.springframework.http.HttpStatus.UNAUTHORIZED;
import org.codiki.domain.category.exception.CategoryDeletionException;
@@ -11,6 +12,8 @@ import org.codiki.domain.exception.LoginFailureException;
import org.codiki.domain.exception.RefreshTokenDoesNotExistException;
import org.codiki.domain.exception.RefreshTokenExpiredException;
import org.codiki.domain.exception.UserDoesNotExistException;
import org.codiki.domain.picture.exception.PictureNotFoundException;
import org.codiki.domain.picture.exception.PictureUploadException;
import org.codiki.domain.publication.exception.PublicationEditionException;
import org.codiki.domain.publication.exception.PublicationNotFoundException;
import org.codiki.domain.publication.exception.PublicationUpdateForbiddenException;
@@ -80,4 +83,16 @@ public class GlobalControllerExceptionHandler {
public void handleCategoryDeletionException() {
// Do nothing.
}
@ResponseStatus(BAD_REQUEST)
@ExceptionHandler(PictureUploadException.class)
public void handlePictureUploadException() {
// Do nothing.
}
@ResponseStatus(NOT_FOUND)
@ExceptionHandler(PictureNotFoundException.class)
public void handlePictureNotFoundException() {
// Do nothing.
}
}

View File

@@ -44,6 +44,7 @@ public class SecurityConfiguration {
GET,
"/api/health/check",
"/api/categories",
"/api/pictures/{pictureId}",
"/error"
).permitAll()
.requestMatchers(

View File

@@ -1,23 +1,44 @@
package org.codiki.exposition.picture;
import static java.util.Objects.isNull;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import org.apache.tika.mime.MimeType;
import org.apache.tika.mime.MimeTypeException;
import org.apache.tika.mime.MimeTypes;
import org.codiki.domain.picture.exception.PictureUploadException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
@Component
public class MultipartFileConverter {
private final String tempPicturesForlderPath;
private static final List<MimeType> ALLOWED_MIME_TYPES;
public MultipartFileConverter(@Value("${application.pictures.temp-path}") String tempPicturesForlderPath) {
this.tempPicturesForlderPath = tempPicturesForlderPath;
static {
MimeTypes mimeTypes = MimeTypes.getDefaultMimeTypes();
try {
ALLOWED_MIME_TYPES = List.of(
mimeTypes.forName("image/png"),
mimeTypes.forName("image/jpeg")
);
} catch (MimeTypeException exception) {
throw new RuntimeException("An error occurred while loading allowed mime types.", exception);
}
}
private final String tempPicturesFolderPath;
public MultipartFileConverter(@Value("${application.pictures.temp-path}") String tempPicturesFolderPath) {
this.tempPicturesFolderPath = tempPicturesFolderPath;
}
public File transformToFile(MultipartFile fileContent) {
File pictureFile = new File(String.format("%s/%s", tempPicturesForlderPath, UUID.randomUUID()));
File pictureFile = new File(buildPicturePath(fileContent));
try {
fileContent.transferTo(pictureFile);
} catch (IOException e) {
@@ -25,4 +46,34 @@ public class MultipartFileConverter {
}
return pictureFile;
}
private String buildPicturePath(MultipartFile fileContent) {
MimeType fileContentType = extractMimeType(fileContent);
return String.format(
"%s/%s%s",
tempPicturesFolderPath,
UUID.randomUUID(),
fileContentType.getExtension()
);
}
private MimeType extractMimeType(MultipartFile fileContent) {
MimeType result = null;
try {
result = MimeTypes.getDefaultMimeTypes()
.forName(fileContent.getContentType());
} catch (MimeTypeException exception) {
// Do nothing
}
if (isNull(result) || !isAllowedMimeType(result)) {
throw new PictureUploadException("Unable to upload the picture because its format is incorrect.");
}
return result;
}
private boolean isAllowedMimeType(MimeType mimeType) {
return ALLOWED_MIME_TYPES.contains(mimeType);
}
}

View File

@@ -3,9 +3,13 @@ package org.codiki.exposition.picture;
import java.io.File;
import java.util.UUID;
import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE;
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
import org.codiki.application.picture.PictureUseCases;
import org.codiki.domain.picture.model.Picture;
import org.springframework.core.io.FileSystemResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -32,4 +36,10 @@ public class PictureController {
Picture newPicture = pictureUseCases.createPicture(pictureFile);
return newPicture.id();
}
@GetMapping(value = "/{pictureId}", produces = APPLICATION_OCTET_STREAM_VALUE)
public FileSystemResource loadPicture(@PathVariable("pictureId") UUID pictureId) {
Picture picture = pictureUseCases.findById(pictureId);
return new FileSystemResource(picture.contentFile());
}
}