From 3b2cd3a78dfcf528d455ef922ca4c58100e480fc Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 9 Apr 2024 18:30:39 +0530 Subject: [PATCH 1/4] define image upload size --- src/main/resources/application.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 9c83768..2efcf0c 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -21,3 +21,7 @@ spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5InnoDBDial springdoc.api-docs.path=/api-docs springdoc.swagger-ui.path=/swagger-ui.html + + +spring.http.multipart.max-file-size=10MB +spring.http.multipart.max-request-size=11MB \ No newline at end of file From 4272e1be1a79bf1a2976ead698c516dfb926a9e0 Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 9 Apr 2024 18:31:12 +0530 Subject: [PATCH 2/4] Handle multipart file --- .../BloggerApp/controller/BlogController.java | 25 +++++++++++++++---- .../http/request/CreateBlogRequest.java | 1 - .../http/response/GetBlogFeedResponse.java | 2 +- .../example/BloggerApp/models/BlogEntity.java | 6 +++-- .../service/impl/BlogServiceImpl.java | 10 ++++++-- 5 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/example/BloggerApp/controller/BlogController.java b/src/main/java/com/example/BloggerApp/controller/BlogController.java index dbbb577..66a9749 100644 --- a/src/main/java/com/example/BloggerApp/controller/BlogController.java +++ b/src/main/java/com/example/BloggerApp/controller/BlogController.java @@ -1,5 +1,6 @@ package com.example.BloggerApp.controller; +import com.example.BloggerApp.common.utils.Base64Converter; import com.example.BloggerApp.http.request.CreateBlogRequest; import com.example.BloggerApp.http.request.TagRequest; import com.example.BloggerApp.http.request.UpdateBlogRequest; @@ -9,11 +10,15 @@ import com.example.BloggerApp.models.BlogEntity; import com.example.BloggerApp.models.TagEntity; import com.example.BloggerApp.service.impl.BlogServiceImpl; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -21,7 +26,10 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.multipart.MultipartRequest; +import java.io.UnsupportedEncodingException; import java.time.LocalDateTime; import java.util.List; import java.util.function.Function; @@ -39,9 +47,17 @@ public BlogController(BlogServiceImpl blogServiceImpl){ } @CrossOrigin(origins = "http://localhost:3000",allowedHeaders = "*") - @PostMapping("/create/user/{user_id}/category/{category_id}") - public ResponseEntity createBlog(@RequestBody CreateBlogRequest createBlogRequest,@PathVariable("user_id") long userId,@PathVariable("category_id") long categoryId){ - blogServiceImpl.addBlog(fromBlogRequestToBlogModel.apply(createBlogRequest),userId,categoryId); + @PostMapping(value = "/create/user/{user_id}/category/{category_id}",consumes = { MediaType.MULTIPART_FORM_DATA_VALUE }) + public ResponseEntity createBlog(@RequestParam("createBlogRequest") String createBlog, @RequestParam("blogCover") MultipartFile blogCover, @PathVariable("user_id") long userId, @PathVariable("category_id") long categoryId) throws Exception { + try { + CreateBlogRequest createBlogRequest = new ObjectMapper().readValue(createBlog, CreateBlogRequest.class); + BlogEntity blogEntity = fromBlogRequestToBlogModel.apply(createBlogRequest); + blogEntity.setImageCover(blogCover.getBytes()); + blogServiceImpl.addBlog(blogEntity, userId, categoryId); + } + catch (Exception ex){ + throw new Exception("Unable to Fetch Post Data from Request"); + } return new ResponseEntity<>("Blog Created",HttpStatus.CREATED); } @@ -104,7 +120,7 @@ private GetBlogResponse apply(BlogEntity blogEntity){ getBlogResponse.setSubtitle(blogEntity.getSubtitle()); getBlogResponse.setGetTagResponses(blogEntity.getTagEntities().stream().map(fromTagModelToTagResponse).collect(Collectors.toList())); getBlogResponse.setBody(blogEntity.getBody()); - getBlogResponse.setImageCover(blogEntity.getImageCover()); + getBlogResponse.setImageCover(Base64Converter.encodeBase64(blogEntity.getImageCover())); getBlogResponse.setCreatedAt(blogEntity.getCreatedAt()); getBlogResponse.setUserId(blogEntity.getUserEntity().getId()); getBlogResponse.setCategoryId(blogEntity.getCategoryEntity().getId()); @@ -134,7 +150,6 @@ private BlogEntity apply(CreateBlogRequest createBlogRequest) { blogEntity.setSubtitle(createBlogRequest.getSubtitle()); blogEntity.setBody(createBlogRequest.getBody()); blogEntity.setTagEntities(createBlogRequest.getTagRequests().stream().map(fromTagRequestToTagModel).collect(Collectors.toList())); - blogEntity.setImageCover(createBlogRequest.getImageCover()); blogEntity.setCreatedAt(LocalDateTime.now()); return blogEntity; } diff --git a/src/main/java/com/example/BloggerApp/http/request/CreateBlogRequest.java b/src/main/java/com/example/BloggerApp/http/request/CreateBlogRequest.java index cc3b912..f6e7fd5 100644 --- a/src/main/java/com/example/BloggerApp/http/request/CreateBlogRequest.java +++ b/src/main/java/com/example/BloggerApp/http/request/CreateBlogRequest.java @@ -14,5 +14,4 @@ public class CreateBlogRequest { private String body; - private String imageCover; } diff --git a/src/main/java/com/example/BloggerApp/http/response/GetBlogFeedResponse.java b/src/main/java/com/example/BloggerApp/http/response/GetBlogFeedResponse.java index 3f3ded7..74c0d30 100644 --- a/src/main/java/com/example/BloggerApp/http/response/GetBlogFeedResponse.java +++ b/src/main/java/com/example/BloggerApp/http/response/GetBlogFeedResponse.java @@ -34,7 +34,7 @@ public class GetBlogFeedResponse { private String createdAt; @JsonProperty("cover") - private String imageCover; + private byte[] imageCover; @JsonProperty("category") private String category; diff --git a/src/main/java/com/example/BloggerApp/models/BlogEntity.java b/src/main/java/com/example/BloggerApp/models/BlogEntity.java index 0fc4901..9a0f104 100644 --- a/src/main/java/com/example/BloggerApp/models/BlogEntity.java +++ b/src/main/java/com/example/BloggerApp/models/BlogEntity.java @@ -35,8 +35,10 @@ public class BlogEntity { private LocalDateTime createdAt; - @NonNull - private String imageCover; + + @Lob + @Basic(fetch = FetchType.LAZY) + private byte[] imageCover; @ManyToOne private CategoryEntity categoryEntity; diff --git a/src/main/java/com/example/BloggerApp/service/impl/BlogServiceImpl.java b/src/main/java/com/example/BloggerApp/service/impl/BlogServiceImpl.java index d6fb05f..7ffac1d 100644 --- a/src/main/java/com/example/BloggerApp/service/impl/BlogServiceImpl.java +++ b/src/main/java/com/example/BloggerApp/service/impl/BlogServiceImpl.java @@ -1,5 +1,6 @@ package com.example.BloggerApp.service.impl; +import com.example.BloggerApp.common.utils.Base64Converter; import com.example.BloggerApp.http.request.TagRequest; import com.example.BloggerApp.http.request.UpdateBlogRequest; import com.example.BloggerApp.http.response.GetBlogFeedResponse; @@ -74,7 +75,12 @@ public BlogEntity updateBlogEntityId(UpdateBlogRequest updateBlogRequest){ blogEntity.getTagEntities().clear(); blogEntity.setTitle(updateBlogRequest.getTitle()); blogEntity.setBody(updateBlogRequest.getBody()); - blogEntity.setImageCover(updateBlogRequest.getImageCover()); + try { + blogEntity.setImageCover(Base64Converter.decodeBase64(updateBlogRequest.getImageCover())); + }catch (Exception ex){ + System.out.println(ex.getMessage()); + } + blogEntity.setSubtitle(updateBlogRequest.getSubtitle()); blogEntity.getTagEntities().addAll(updateBlogRequest.getTagRequests().stream().map(fromTagRequestToTagEntity).collect(Collectors.toList())); return blogRepository.save(blogEntity); @@ -111,7 +117,7 @@ public List getBlogEntitiesByUserId(Long userId) { getBlogFeedResponse.setId(id.longValue()); getBlogFeedResponse.setTitle((String) map.get("title")); getBlogFeedResponse.setContent((String) map.get("body")); - getBlogFeedResponse.setImageCover((String) map.get("cover")); + getBlogFeedResponse.setImageCover((byte[]) map.get("cover")); getBlogFeedResponse.setCategory((String) map.get("category")); getBlogFeedResponse.setAuthorName((String) map.get("username")); getBlogFeedResponse.setAuthorAvatar((String) map.get("image")); From 96e0369dc2ce1cc98fa8f4f2052418dd1c44de82 Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 9 Apr 2024 18:32:04 +0530 Subject: [PATCH 3/4] create controller and service for image upload --- .../common/utils/Base64Converter.java | 16 +++++++ .../BloggerApp/common/utils/ImageUtils.java | 45 +++++++++++++++++++ .../BloggerApp/models/ImageEntity.java | 40 +++++++++++++++++ .../repository/ImageRepository.java | 9 ++++ .../BloggerApp/service/ImageService.java | 11 +++++ .../service/impl/ImageServiceImpl.java | 36 +++++++++++++++ 6 files changed, 157 insertions(+) create mode 100644 src/main/java/com/example/BloggerApp/common/utils/Base64Converter.java create mode 100644 src/main/java/com/example/BloggerApp/common/utils/ImageUtils.java create mode 100644 src/main/java/com/example/BloggerApp/models/ImageEntity.java create mode 100644 src/main/java/com/example/BloggerApp/repository/ImageRepository.java create mode 100644 src/main/java/com/example/BloggerApp/service/ImageService.java create mode 100644 src/main/java/com/example/BloggerApp/service/impl/ImageServiceImpl.java diff --git a/src/main/java/com/example/BloggerApp/common/utils/Base64Converter.java b/src/main/java/com/example/BloggerApp/common/utils/Base64Converter.java new file mode 100644 index 0000000..f4ef2cc --- /dev/null +++ b/src/main/java/com/example/BloggerApp/common/utils/Base64Converter.java @@ -0,0 +1,16 @@ +package com.example.BloggerApp.common.utils; + +import java.io.UnsupportedEncodingException; +import java.nio.charset.StandardCharsets; +import java.util.Base64; + +public class Base64Converter { + + public static byte[] decodeBase64(String base64String) throws UnsupportedEncodingException { + return Base64.getMimeDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); + } + + public static String encodeBase64(byte[] image){ + return Base64.getEncoder().encodeToString(image); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/BloggerApp/common/utils/ImageUtils.java b/src/main/java/com/example/BloggerApp/common/utils/ImageUtils.java new file mode 100644 index 0000000..6f477ed --- /dev/null +++ b/src/main/java/com/example/BloggerApp/common/utils/ImageUtils.java @@ -0,0 +1,45 @@ +package com.example.BloggerApp.common.utils; + +import java.io.ByteArrayOutputStream; +import java.util.zip.Deflater; +import java.util.zip.Inflater; + +public class ImageUtils { + + public static byte[] compressImage(byte[] data) { + Deflater deflater = new Deflater(); + deflater.setLevel(Deflater.BEST_COMPRESSION); + deflater.setInput(data); + deflater.finish(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); + byte[] tmp = new byte[4*1024]; + while (!deflater.finished()) { + int size = deflater.deflate(tmp); + outputStream.write(tmp, 0, size); + } + try { + outputStream.close(); + } catch (Exception ignored) { + } + return outputStream.toByteArray(); + } + + + + public static byte[] decompressImage(byte[] data) { + Inflater inflater = new Inflater(); + inflater.setInput(data); + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length); + byte[] tmp = new byte[4*1024]; + try { + while (!inflater.finished()) { + int count = inflater.inflate(tmp); + outputStream.write(tmp, 0, count); + } + outputStream.close(); + } catch (Exception ignored) { + } + return outputStream.toByteArray(); + } +} diff --git a/src/main/java/com/example/BloggerApp/models/ImageEntity.java b/src/main/java/com/example/BloggerApp/models/ImageEntity.java new file mode 100644 index 0000000..9dae72a --- /dev/null +++ b/src/main/java/com/example/BloggerApp/models/ImageEntity.java @@ -0,0 +1,40 @@ +package com.example.BloggerApp.models; + + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.CascadeType; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Lob; +import javax.persistence.OneToOne; + +@Entity +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor(force = true) +@Builder +public class ImageEntity { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + @Column(name = "id", nullable = false) + private Long id; + + private String name; + + private String type; + + @Lob + private byte[] imageData; + + + +} diff --git a/src/main/java/com/example/BloggerApp/repository/ImageRepository.java b/src/main/java/com/example/BloggerApp/repository/ImageRepository.java new file mode 100644 index 0000000..b1d948b --- /dev/null +++ b/src/main/java/com/example/BloggerApp/repository/ImageRepository.java @@ -0,0 +1,9 @@ +package com.example.BloggerApp.repository; + +import com.example.BloggerApp.models.ImageEntity; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ImageRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/BloggerApp/service/ImageService.java b/src/main/java/com/example/BloggerApp/service/ImageService.java new file mode 100644 index 0000000..1c3375b --- /dev/null +++ b/src/main/java/com/example/BloggerApp/service/ImageService.java @@ -0,0 +1,11 @@ +package com.example.BloggerApp.service; + +import com.example.BloggerApp.models.ImageEntity; +import org.springframework.web.multipart.MultipartFile; + +public interface ImageService { + + ImageEntity uploadImage(MultipartFile file); + + ImageEntity downloadImage(Long imageId); +} diff --git a/src/main/java/com/example/BloggerApp/service/impl/ImageServiceImpl.java b/src/main/java/com/example/BloggerApp/service/impl/ImageServiceImpl.java new file mode 100644 index 0000000..df258fc --- /dev/null +++ b/src/main/java/com/example/BloggerApp/service/impl/ImageServiceImpl.java @@ -0,0 +1,36 @@ +package com.example.BloggerApp.service.impl; + +import com.example.BloggerApp.common.utils.ImageUtils; +import com.example.BloggerApp.models.ImageEntity; +import com.example.BloggerApp.repository.ImageRepository; +import com.example.BloggerApp.service.ImageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +@Service +public class ImageServiceImpl implements ImageService { + + @Autowired + private ImageRepository imageRepository; + @Override + public ImageEntity uploadImage(MultipartFile file) { + ImageEntity imageEntity = new ImageEntity(); + imageEntity.setName(file.getName()); + imageEntity.setType(file.getContentType()); + try { + imageEntity.setImageData(ImageUtils.compressImage(file.getBytes())); + }catch (Exception ex){ + System.out.println(ex.getMessage()); + } + + return imageRepository.save(imageEntity); + } + + @Override + public ImageEntity downloadImage(Long imageId) { + return imageRepository.findById(imageId).get(); + } +} From 076ca4b787f6cbd00ae77a8979081b341346f067 Mon Sep 17 00:00:00 2001 From: Rohit Date: Tue, 9 Apr 2024 18:35:12 +0530 Subject: [PATCH 4/4] handle error in Blog test class --- .../com/example/BloggerApp/service/BlogServiceTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/example/BloggerApp/service/BlogServiceTest.java b/src/test/java/com/example/BloggerApp/service/BlogServiceTest.java index f567913..02a7114 100644 --- a/src/test/java/com/example/BloggerApp/service/BlogServiceTest.java +++ b/src/test/java/com/example/BloggerApp/service/BlogServiceTest.java @@ -73,7 +73,7 @@ public void addBlog_ValidInput_Success(){ BlogEntity blogEntity = new BlogEntity(); blogEntity.setSubtitle("Blog-Subtitle"); blogEntity.setBody("This is test blog entity body"); - blogEntity.setImageCover("Test image cover"); + // blogEntity.setImageCover("Test image cover"); blogEntity.setTitle("DSA"); blogEntity.setCreatedAt(LocalDateTime.now()); @@ -91,7 +91,7 @@ public void addBlog_ValidInput_Success(){ savedBlogEntity.setId(1L); savedBlogEntity.setSubtitle("Blog-Subtitle"); savedBlogEntity.setBody("This is test blog entity body"); - savedBlogEntity.setImageCover("Test image cover"); + // savedBlogEntity.setImageCover("Test image cover"); savedBlogEntity.setTitle("DSA"); savedBlogEntity.setCreatedAt(LocalDateTime.now()); @@ -135,7 +135,7 @@ public void getBlogById_ValidInput_Success(){ savedBlogEntity.setId(1L); savedBlogEntity.setSubtitle("Blog-Subtitle"); savedBlogEntity.setBody("This is test blog entity body"); - savedBlogEntity.setImageCover("Test image cover"); + // savedBlogEntity.setImageCover("Test image cover"); savedBlogEntity.setTitle("DSA"); savedBlogEntity.setCreatedAt(LocalDateTime.now()); @@ -182,7 +182,7 @@ public void deleteById_ValidInput_Success(){ savedBlogEntity.setId(1L); savedBlogEntity.setSubtitle("Blog-Subtitle"); savedBlogEntity.setBody("This is test blog entity body"); - savedBlogEntity.setImageCover("Test image cover"); + // savedBlogEntity.setImageCover("Test image cover"); savedBlogEntity.setTitle("DSA"); savedBlogEntity.setCreatedAt(LocalDateTime.now());