-
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.
Add the capability to upload article images
- Loading branch information
1 parent
da3c3c6
commit f0f1064
Showing
22 changed files
with
559 additions
and
1 deletion.
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
21 changes: 21 additions & 0 deletions
21
src/main/java/me/ezzedine/mohammed/personalspace/article/api/image/ArticleImageApi.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,21 @@ | ||
package me.ezzedine.mohammed.personalspace.article.api.image; | ||
|
||
import me.ezzedine.mohammed.personalspace.article.core.image.FailedToUploadImageException; | ||
import me.ezzedine.mohammed.personalspace.article.core.image.ImageDoesNotExistException; | ||
import me.ezzedine.mohammed.personalspace.article.core.image.ImageNameAlreadyExistsException; | ||
import me.ezzedine.mohammed.personalspace.config.security.AdminAccess; | ||
import org.springframework.core.io.Resource; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
@RequestMapping("articles/images") | ||
public interface ArticleImageApi { | ||
|
||
@PostMapping | ||
@AdminAccess | ||
ResponseEntity<UploadImageApiResponse> uploadImage(@RequestParam("upload") MultipartFile image) throws ImageNameAlreadyExistsException, FailedToUploadImageException; | ||
|
||
@GetMapping("{name}") | ||
ResponseEntity<Resource> serveImage(@PathVariable String name) throws ImageDoesNotExistException; | ||
} |
54 changes: 54 additions & 0 deletions
54
...ain/java/me/ezzedine/mohammed/personalspace/article/api/image/ArticleImageController.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,54 @@ | ||
package me.ezzedine.mohammed.personalspace.article.api.image; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.SneakyThrows; | ||
import lombok.extern.slf4j.Slf4j; | ||
import me.ezzedine.mohammed.personalspace.article.core.image.ArticleImageService; | ||
import me.ezzedine.mohammed.personalspace.article.core.image.FailedToUploadImageException; | ||
import me.ezzedine.mohammed.personalspace.article.core.image.ImageDoesNotExistException; | ||
import me.ezzedine.mohammed.personalspace.article.core.image.ImageNameAlreadyExistsException; | ||
import org.springframework.core.io.Resource; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.multipart.MultipartFile; | ||
|
||
import java.io.IOException; | ||
|
||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; | ||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; | ||
|
||
@Slf4j | ||
@RestController | ||
@RequiredArgsConstructor | ||
public class ArticleImageController implements ArticleImageApi { | ||
|
||
private final ArticleImageService imageService; | ||
|
||
@Override | ||
public ResponseEntity<UploadImageApiResponse> uploadImage(MultipartFile image) throws ImageNameAlreadyExistsException, FailedToUploadImageException { | ||
log.info("Received a request to upload the image {}", image.getOriginalFilename()); | ||
try { | ||
imageService.upload(image.getOriginalFilename(), image.getBytes()); | ||
} catch (IOException e) { | ||
throw new FailedToUploadImageException(e.getMessage()); | ||
} | ||
|
||
UploadImageApiResponse response = UploadImageApiResponse.builder().url(getImageLink(image)).build(); | ||
return ResponseEntity.ok().body(response); | ||
} | ||
|
||
@SneakyThrows | ||
private static String getImageLink(MultipartFile image) { | ||
return linkTo(methodOn(ArticleImageController.class).serveImage(image.getOriginalFilename())).toUri().toString(); | ||
} | ||
|
||
@Override | ||
public ResponseEntity<Resource> serveImage(String name) throws ImageDoesNotExistException { | ||
log.info("Received a request to serve the image {}", name); | ||
Resource resource = imageService.serveImage(name); | ||
return ResponseEntity.ok() | ||
.header(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment; filename=\"%s\"", resource.getFilename())) | ||
.body(resource); | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
...ain/java/me/ezzedine/mohammed/personalspace/article/api/image/UploadImageApiResponse.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 me.ezzedine.mohammed.personalspace.article.api.image; | ||
|
||
import lombok.Builder; | ||
import lombok.Data; | ||
|
||
@Data | ||
@Builder | ||
public class UploadImageApiResponse { | ||
private String url; | ||
} |
19 changes: 19 additions & 0 deletions
19
...e/ezzedine/mohammed/personalspace/article/api/image/advice/FailedToUploadImageAdvice.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,19 @@ | ||
package me.ezzedine.mohammed.personalspace.article.api.image.advice; | ||
|
||
import me.ezzedine.mohammed.personalspace.article.core.image.FailedToUploadImageException; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.context.request.WebRequest; | ||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; | ||
|
||
@ControllerAdvice | ||
public class FailedToUploadImageAdvice extends ResponseEntityExceptionHandler { | ||
|
||
@ExceptionHandler(FailedToUploadImageException.class) | ||
protected ResponseEntity<Object> handle(FailedToUploadImageException exception, WebRequest request) { | ||
return handleExceptionInternal(exception, exception.getMessage(), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
.../me/ezzedine/mohammed/personalspace/article/api/image/advice/ImageDoesNotExistAdvice.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,19 @@ | ||
package me.ezzedine.mohammed.personalspace.article.api.image.advice; | ||
|
||
import me.ezzedine.mohammed.personalspace.article.core.image.ImageDoesNotExistException; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.context.request.WebRequest; | ||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; | ||
|
||
@ControllerAdvice | ||
public class ImageDoesNotExistAdvice extends ResponseEntityExceptionHandler { | ||
|
||
@ExceptionHandler(ImageDoesNotExistException.class) | ||
protected ResponseEntity<Object> handle(ImageDoesNotExistException exception, WebRequest request) { | ||
return handleExceptionInternal(exception, exception.getMessage(), new HttpHeaders(), HttpStatus.NOT_FOUND, request); | ||
} | ||
} |
19 changes: 19 additions & 0 deletions
19
...zzedine/mohammed/personalspace/article/api/image/advice/ImageNameAlreadyExistsAdvice.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,19 @@ | ||
package me.ezzedine.mohammed.personalspace.article.api.image.advice; | ||
|
||
import me.ezzedine.mohammed.personalspace.article.core.image.ImageNameAlreadyExistsException; | ||
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.ControllerAdvice; | ||
import org.springframework.web.bind.annotation.ExceptionHandler; | ||
import org.springframework.web.context.request.WebRequest; | ||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; | ||
|
||
@ControllerAdvice | ||
public class ImageNameAlreadyExistsAdvice extends ResponseEntityExceptionHandler { | ||
|
||
@ExceptionHandler(ImageNameAlreadyExistsException.class) | ||
protected ResponseEntity<Object> handle(ImageNameAlreadyExistsException exception, WebRequest request) { | ||
return handleExceptionInternal(exception, exception.getMessage(), new HttpHeaders(), HttpStatus.CONFLICT, request); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
.../java/me/ezzedine/mohammed/personalspace/article/core/image/ArticleImagePathResolver.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,7 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
import java.nio.file.Path; | ||
|
||
public interface ArticleImagePathResolver { | ||
Path resolve(String imageName); | ||
} |
8 changes: 8 additions & 0 deletions
8
src/main/java/me/ezzedine/mohammed/personalspace/article/core/image/ArticleImageService.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,8 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
import org.springframework.core.io.Resource; | ||
|
||
public interface ArticleImageService { | ||
void upload(String name, byte[] content) throws ImageNameAlreadyExistsException, FailedToUploadImageException; | ||
Resource serveImage(String name) throws ImageDoesNotExistException; | ||
} |
5 changes: 5 additions & 0 deletions
5
...e/ezzedine/mohammed/personalspace/article/core/image/ArticleImagesStoragePathFactory.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,5 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
public interface ArticleImagesStoragePathFactory { | ||
String get(); | ||
} |
19 changes: 19 additions & 0 deletions
19
.../ezzedine/mohammed/personalspace/article/core/image/ConcreteArticleImagePathResolver.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,19 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class ConcreteArticleImagePathResolver implements ArticleImagePathResolver { | ||
|
||
private final ArticleImagesStoragePathFactory storagePathFactory; | ||
|
||
@Override | ||
public Path resolve(String imageName) { | ||
return Paths.get(storagePathFactory.get(), imageName); | ||
} | ||
} |
46 changes: 46 additions & 0 deletions
46
...va/me/ezzedine/mohammed/personalspace/article/core/image/ConcreteArticleImageService.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,46 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.SneakyThrows; | ||
import org.springframework.core.io.Resource; | ||
import org.springframework.core.io.UrlResource; | ||
import org.springframework.stereotype.Service; | ||
|
||
import java.io.IOException; | ||
import java.net.MalformedURLException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
|
||
@Service | ||
@RequiredArgsConstructor | ||
public class ConcreteArticleImageService implements ArticleImageService { | ||
|
||
private final ArticleImagePathResolver pathResolver; | ||
|
||
@Override | ||
public void upload(String name, byte[] content) throws ImageNameAlreadyExistsException, FailedToUploadImageException { | ||
Path imagePath = pathResolver.resolve(name); | ||
|
||
if (Files.exists(imagePath)) { | ||
throw new ImageNameAlreadyExistsException(name); | ||
} | ||
|
||
try { | ||
Files.createDirectories(imagePath.getParent()); | ||
Files.write(imagePath, content); | ||
} catch (IOException e) { | ||
throw new FailedToUploadImageException(e.getMessage()); | ||
} | ||
} | ||
|
||
@Override | ||
@SneakyThrows(MalformedURLException.class) | ||
public Resource serveImage(String name) throws ImageDoesNotExistException { | ||
Path imagePath = pathResolver.resolve(name); | ||
if (Files.notExists(imagePath)) { | ||
throw new ImageDoesNotExistException(name); | ||
} | ||
|
||
return new UrlResource(imagePath.toUri()); | ||
} | ||
} |
16 changes: 16 additions & 0 deletions
16
...ne/mohammed/personalspace/article/core/image/ConcreteArticleImagesStoragePathFactory.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,16 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
import org.springframework.stereotype.Service; | ||
|
||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
|
||
@Service | ||
public class ConcreteArticleImagesStoragePathFactory implements ArticleImagesStoragePathFactory { | ||
|
||
@Override | ||
public String get() { | ||
Path path = Paths.get(System.getProperty("user.dir"), "article-images"); | ||
return path.toString(); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...a/me/ezzedine/mohammed/personalspace/article/core/image/FailedToUploadImageException.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,7 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
public class FailedToUploadImageException extends Exception { | ||
public FailedToUploadImageException(String message) { | ||
super(message); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...ava/me/ezzedine/mohammed/personalspace/article/core/image/ImageDoesNotExistException.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,7 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
public class ImageDoesNotExistException extends Exception { | ||
public ImageDoesNotExistException(String name) { | ||
super(String.format("Image '%s' does not exist in the storage", name)); | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...e/ezzedine/mohammed/personalspace/article/core/image/ImageNameAlreadyExistsException.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,7 @@ | ||
package me.ezzedine.mohammed.personalspace.article.core.image; | ||
|
||
public class ImageNameAlreadyExistsException extends Exception { | ||
public ImageNameAlreadyExistsException(String name) { | ||
super(String.format("Image name %s already exists.", name)); | ||
} | ||
} |
Oops, something went wrong.