Skip to content

Commit e692bb4

Browse files
committed
Product image and image gallery are implemented.
1 parent bb2ac8e commit e692bb4

File tree

12 files changed

+242
-6
lines changed

12 files changed

+242
-6
lines changed

src/main/java/com/manir/springbootecommercerestapi/controller/ProductController.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@
44
import com.manir.springbootecommercerestapi.service.ProductService;
55
import org.springframework.beans.factory.annotation.Autowired;
66
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.MediaType;
78
import org.springframework.http.ResponseEntity;
89
import org.springframework.web.bind.annotation.*;
10+
import org.springframework.web.multipart.MultipartFile;
911

12+
import java.io.IOException;
1013
import java.util.List;
1114

1215
@RestController
@@ -17,9 +20,10 @@ public class ProductController {
1720
private ProductService productService;
1821

1922
//product create api
20-
@PostMapping("/createProduct")
21-
public ResponseEntity<ProductDto> createProduct(@RequestBody ProductDto productDto){
22-
ProductDto responseProduct = productService.createProduct(productDto);
23+
@RequestMapping(value = "/createProduct", method = RequestMethod.POST, consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.MULTIPART_FORM_DATA_VALUE})
24+
public ResponseEntity<ProductDto> createProduct(@RequestPart("productDto") ProductDto productDto,
25+
@RequestPart("file") MultipartFile file){
26+
ProductDto responseProduct = productService.createProduct(productDto, file);
2327
return new ResponseEntity<>(responseProduct, HttpStatus.CREATED);
2428
}
2529

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.manir.springbootecommercerestapi.controller;
2+
3+
import com.manir.springbootecommercerestapi.resource.ImageData;
4+
import com.manir.springbootecommercerestapi.service.ProductImageGalleryService;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.http.HttpStatus;
7+
import org.springframework.http.ResponseEntity;
8+
import org.springframework.web.bind.annotation.*;
9+
import org.springframework.web.multipart.MultipartFile;
10+
11+
@RestController
12+
@RequestMapping(value = "api/v1/products")
13+
public class ProductImageGalleryController {
14+
15+
@Autowired
16+
private ProductImageGalleryService productImageGalleryService;
17+
18+
19+
//add image to product api
20+
@PostMapping("/{productId}/addImage")
21+
public ResponseEntity<String> addImageToProduct(@PathVariable Long productId,
22+
@RequestParam("file")MultipartFile file){
23+
productImageGalleryService.addImageToProduct(productId, file);
24+
return new ResponseEntity<>("Image successfully added to product with id : " + productId, HttpStatus.CREATED);
25+
}
26+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.manir.springbootecommercerestapi.dto;
2+
3+
import lombok.Data;
4+
5+
@Data
6+
public class ImageDataDto {
7+
8+
private Long id;
9+
private String name;
10+
private String type;
11+
private byte[] imageData;
12+
13+
}

src/main/java/com/manir/springbootecommercerestapi/dto/ProductDto.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package com.manir.springbootecommercerestapi.dto;
2+
import com.manir.springbootecommercerestapi.resource.ImageData;
23
import lombok.Data;
34

5+
import java.util.List;
6+
import java.util.Set;
7+
48
@Data
59
public class ProductDto {
610
private Long id;
@@ -12,5 +16,9 @@ public class ProductDto {
1216
private Integer quantity;
1317
private String status;
1418

19+
private String image;
20+
1521
private CategoryDto category;
22+
23+
private Set<ImageDataDto> images;
1624
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package com.manir.springbootecommercerestapi.repository;
2+
3+
import com.manir.springbootecommercerestapi.resource.ImageData;
4+
import org.springframework.data.jpa.repository.JpaRepository;
5+
6+
public interface ProductImageGalleryRepository extends JpaRepository<ImageData, Long> {
7+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.manir.springbootecommercerestapi.resource;
2+
3+
import lombok.*;
4+
5+
import javax.persistence.*;
6+
7+
@Getter
8+
@Setter
9+
@AllArgsConstructor
10+
@NoArgsConstructor
11+
@Entity
12+
@Table(name = "product_image_gallery")
13+
public class ImageData {
14+
@Id
15+
@GeneratedValue(strategy = GenerationType.IDENTITY)
16+
private Long id;
17+
@Column(name = "name")
18+
private String name;
19+
@Column(name = "type")
20+
private String type;
21+
22+
@Column(name = "imageData", length = 1000)
23+
@Lob
24+
private byte[] imageData;
25+
26+
//relation with product entity
27+
@ManyToOne(fetch = FetchType.EAGER)
28+
@JoinColumn(name = "product_id")
29+
private Product product;
30+
31+
}

src/main/java/com/manir/springbootecommercerestapi/resource/Product.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import lombok.*;
44

55
import javax.persistence.*;
6+
import java.util.List;
7+
import java.util.Set;
68

79
@AllArgsConstructor
810
@NoArgsConstructor
@@ -29,8 +31,18 @@ public class Product {
2931
@Column(name = "status")
3032
private String status;
3133

34+
//product image
35+
@Lob
36+
@Column(name = "image")
37+
private String image;
38+
39+
3240
//relation between category and product
3341
@ManyToOne(fetch = FetchType.LAZY)
3442
@JoinColumn(name = "category_id")
35-
Category category;
43+
private Category category;
44+
45+
//relation image gallery
46+
@OneToMany(mappedBy = "product", cascade = CascadeType.ALL, orphanRemoval = true)
47+
private Set<ImageData> images;
3648
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package com.manir.springbootecommercerestapi.service.Impl;
2+
3+
import com.manir.springbootecommercerestapi.exception.ResourceNotFoundException;
4+
import com.manir.springbootecommercerestapi.repository.ProductImageGalleryRepository;
5+
import com.manir.springbootecommercerestapi.repository.ProductRepository;
6+
import com.manir.springbootecommercerestapi.resource.ImageData;
7+
import com.manir.springbootecommercerestapi.resource.Product;
8+
import com.manir.springbootecommercerestapi.service.ProductImageGalleryService;
9+
import com.manir.springbootecommercerestapi.utils.ImageUtils;
10+
import org.springframework.stereotype.Service;
11+
import org.springframework.web.multipart.MultipartFile;
12+
13+
import javax.annotation.Resource;
14+
import java.io.IOException;
15+
16+
@Service
17+
public class ProductImageGalleryServiceImpl implements ProductImageGalleryService {
18+
19+
@Resource
20+
private ProductImageGalleryRepository productImageGalleryRepository;
21+
@Resource
22+
private ProductRepository productRepository;
23+
24+
@Override
25+
public ImageData addImageToProduct(Long productId, MultipartFile file) {
26+
27+
Product product = productRepository.findById(productId)
28+
.orElseThrow(
29+
() -> new ResourceNotFoundException("Product", productId)
30+
);
31+
32+
ImageData addedImage = null;
33+
try {
34+
addedImage = productImageGalleryRepository.save(uploadImage(file,product));
35+
} catch (IOException e) {
36+
throw new RuntimeException(e);
37+
}
38+
39+
return addedImage;
40+
}
41+
42+
43+
private ImageData uploadImage(MultipartFile file, Product product ) throws IOException {
44+
ImageData imageData = new ImageData();
45+
imageData.setName(file.getOriginalFilename());
46+
imageData.setType(file.getContentType());
47+
imageData.setImageData(ImageUtils.compressImage(file.getBytes()));
48+
49+
imageData.setProduct(product);
50+
return imageData;
51+
}
52+
53+
54+
}

src/main/java/com/manir/springbootecommercerestapi/service/Impl/ProductServiceImpl.java

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@
55
import com.manir.springbootecommercerestapi.repository.CategoryRepository;
66
import com.manir.springbootecommercerestapi.repository.ProductRepository;
77
import com.manir.springbootecommercerestapi.resource.Category;
8+
import com.manir.springbootecommercerestapi.resource.ImageData;
89
import com.manir.springbootecommercerestapi.resource.Product;
910
import com.manir.springbootecommercerestapi.service.ProductService;
11+
import com.manir.springbootecommercerestapi.utils.ImageUtils;
1012
import org.modelmapper.ModelMapper;
1113
import org.springframework.stereotype.Service;
14+
import org.springframework.util.StringUtils;
15+
import org.springframework.web.multipart.MultipartFile;
1216

1317
import javax.annotation.Resource;
18+
import java.io.IOException;
19+
import java.util.Base64;
1420
import java.util.List;
1521
import java.util.stream.Collectors;
1622

@@ -25,8 +31,9 @@ public class ProductServiceImpl implements ProductService {
2531
private CategoryRepository categoryRepository;
2632

2733
@Override
28-
public ProductDto createProduct(ProductDto productDto) {
34+
public ProductDto createProduct(ProductDto productDto, MultipartFile file) {
2935
//map to entity
36+
productDto.setImage(uploadProductImage(file));
3037
Product product = mapToEntity(productDto);
3138
Product createdProduct = productRepository.save(product);
3239
//map to dto
@@ -105,6 +112,22 @@ public ProductDto saveProductByCategoryId(Long categoryId, ProductDto productDto
105112
return responseProduct;
106113
}
107114

115+
//upload image
116+
private String uploadProductImage(MultipartFile file){
117+
ProductDto productDto = new ProductDto();
118+
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
119+
if(fileName.contains("..")){
120+
System.out.println("Not a valid file");
121+
}
122+
try {
123+
productDto.setImage(Base64.getEncoder().encodeToString(file.getBytes()));
124+
} catch (IOException e) {
125+
throw new RuntimeException(e);
126+
}
127+
return productDto.getImage();
128+
}
129+
130+
108131
//map to dto
109132
private ProductDto mapToDto(Product product){
110133
ProductDto productDto = modelMapper.map(product, ProductDto.class);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.manir.springbootecommercerestapi.service;
2+
3+
import com.manir.springbootecommercerestapi.resource.ImageData;
4+
import org.springframework.web.multipart.MultipartFile;
5+
6+
public interface ProductImageGalleryService {
7+
8+
ImageData addImageToProduct(Long productId, MultipartFile file);
9+
10+
}

src/main/java/com/manir/springbootecommercerestapi/service/ProductService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.manir.springbootecommercerestapi.service;
22

33
import com.manir.springbootecommercerestapi.dto.ProductDto;
4+
import org.springframework.web.multipart.MultipartFile;
45

56
import java.util.List;
67

78
public interface ProductService {
8-
ProductDto createProduct(ProductDto productDto);
9+
ProductDto createProduct(ProductDto productDto, MultipartFile file);
910
List<ProductDto> getAllProduct();
1011
ProductDto getProductById(Long productId);
1112
ProductDto updateProduct(Long categoryId, ProductDto productDto, Long productId);
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.manir.springbootecommercerestapi.utils;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import java.util.zip.Deflater;
5+
import java.util.zip.Inflater;
6+
7+
public class ImageUtils {
8+
9+
public static byte[] compressImage(byte[] data) {
10+
Deflater deflater = new Deflater();
11+
deflater.setLevel(Deflater.BEST_COMPRESSION);
12+
deflater.setInput(data);
13+
deflater.finish();
14+
15+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
16+
byte[] tmp = new byte[4*1024];
17+
while (!deflater.finished()) {
18+
int size = deflater.deflate(tmp);
19+
outputStream.write(tmp, 0, size);
20+
}
21+
try {
22+
outputStream.close();
23+
} catch (Exception ignored) {
24+
}
25+
return outputStream.toByteArray();
26+
}
27+
28+
29+
30+
public static byte[] decompressImage(byte[] data) {
31+
Inflater inflater = new Inflater();
32+
inflater.setInput(data);
33+
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
34+
byte[] tmp = new byte[4*1024];
35+
try {
36+
while (!inflater.finished()) {
37+
int count = inflater.inflate(tmp);
38+
outputStream.write(tmp, 0, count);
39+
}
40+
outputStream.close();
41+
} catch (Exception ignored) {
42+
}
43+
return outputStream.toByteArray();
44+
}
45+
46+
47+
}

0 commit comments

Comments
 (0)