Skip to content

Commit

Permalink
Merge pull request #603 from bounswe/feature/BE-591-backend-handle-im…
Browse files Browse the repository at this point in the history
…age-upload

#591 Implemented Image upload to resources using amazon s3 bucket.
  • Loading branch information
furknbulbul committed Dec 24, 2023
2 parents db5d29b + 23a14cc commit 4c35d75
Show file tree
Hide file tree
Showing 14 changed files with 174 additions and 15 deletions.
10 changes: 10 additions & 0 deletions resq/backend/resq/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.133</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.firebase/firebase-admin
<dependency>
<groupId>com.google.firebase</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package com.groupa1.resq.config;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.PutObjectRequest;
import jakarta.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;

@Service
public class AmazonClient {

private AmazonS3 s3client;
@Value("${amazonProperties.endpointUrl}")
private String endpointUrl;

@Value("${amazonProperties.bucketName}")
private String bucketName;

@Value("${amazonProperties.accessKey}")
private String accessKey;

@Value("${amazonProperties.secretKey}")
private String secretKey;

@PostConstruct
private void initializeAmazon() {
AWSCredentials credentials = new BasicAWSCredentials(this.accessKey, this.secretKey);
this.s3client = new AmazonS3Client(credentials);
}

private File convertMultiPartToFile(MultipartFile file) throws IOException {
File convFile = new File(file.getOriginalFilename());
FileOutputStream fos = new FileOutputStream(convFile);
fos.write(file.getBytes());
fos.close();
return convFile;
}

private String generateFileName(MultipartFile multiPart) {
return new Date().getTime() + "-" + multiPart.getOriginalFilename().replace(" ", "_");
}

private void uploadFileTos3bucket(String fileName, File file) {
s3client.putObject(new PutObjectRequest(bucketName, fileName, file)
.withCannedAcl(CannedAccessControlList.PublicRead));
}

public com.groupa1.resq.entity.File uploadFile(MultipartFile multipartFile) {
com.groupa1.resq.entity.File fileEntity = new com.groupa1.resq.entity.File();
String fileUrl = "";
String fileName = generateFileName(multipartFile);
try {
File file = convertMultiPartToFile(multipartFile);
fileUrl = endpointUrl + "/" + bucketName + "/" + fileName;
uploadFileTos3bucket(fileName, file);
file.delete();
} catch (Exception e) {
e.printStackTrace();
}
fileEntity.setFileName(fileName);
fileEntity.setFileUrl(fileUrl);
fileEntity.setFileType(multipartFile.getContentType());
return fileEntity;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.groupa1.resq.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.groupa1.resq.dto.ResourceDto;
import com.groupa1.resq.entity.enums.EResourceStatus;
import com.groupa1.resq.request.CreateResourceRequest;
Expand All @@ -9,6 +10,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.List;
Expand All @@ -24,9 +26,10 @@ public class ResourceController {

@PreAuthorize("hasRole('RESPONDER')")
@PostMapping("/createResource")
public ResponseEntity<Object> createResource(@RequestBody CreateResourceRequest createResourceRequest) {
public ResponseEntity<Object> createResource(@RequestPart(name = "createResourceRequest") CreateResourceRequest createResourceRequest,
@RequestPart(name = "file", required = false) MultipartFile file) {
log.info("Creating resource with request: " + createResourceRequest.toString());
return resourceService.createResource(createResourceRequest);
return resourceService.createResource(createResourceRequest, file);
}

@PreAuthorize("hasRole('RESPONDER') or hasRole('COORDINATOR') or hasRole('VICTIM')")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.groupa1.resq.converter;

import com.groupa1.resq.dto.FileDto;
import com.groupa1.resq.dto.ResourceDto;
import com.groupa1.resq.entity.Resource;
import com.groupa1.resq.entity.enums.ESize;
import com.groupa1.resq.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -32,7 +32,14 @@ public ResourceDto convertToDto(Resource resource){
}

if (resource.getSize() != null)
resourceDto.setSize(resource.getSize().toString());
resourceDto.setSize(resource.getSize());
if (resource.getFile() != null){
FileDto fileDto = new FileDto();
fileDto.setFileName(resource.getFile().getFileName());
fileDto.setFileUrl(resource.getFile().getFileUrl());
fileDto.setFileType(resource.getFile().getFileType());
resourceDto.setFile(fileDto);
}
return resourceDto;

}
Expand All @@ -55,7 +62,7 @@ public Resource convertToEntity(ResourceDto resourceDto){
resource.setLongitude(resourceDto.getLongitude());
resource.setCreatedAt(resourceDto.getCreatedDate());
if (resourceDto.getSize() != null)
resource.setSize(ESize.valueOf(resourceDto.getSize()));
resource.setSize(resourceDto.getSize());
return resource;
}
}
10 changes: 10 additions & 0 deletions resq/backend/resq/src/main/java/com/groupa1/resq/dto/FileDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.groupa1.resq.dto;

import lombok.Data;

@Data
public class FileDto {
private String fileName;
private String fileUrl;
private String fileType;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.groupa1.resq.dto;

import com.groupa1.resq.entity.enums.EGender;
import com.groupa1.resq.entity.enums.ESize;
import com.groupa1.resq.entity.enums.EResourceStatus;
import jakarta.persistence.Access;
import lombok.Data;
Expand All @@ -21,6 +22,7 @@ public class ResourceDto {
private BigDecimal latitude;
private BigDecimal longitude;
private LocalDateTime createdDate;
private String size;
private ESize size;
private FileDto file;
private EResourceStatus status;
}
23 changes: 23 additions & 0 deletions resq/backend/resq/src/main/java/com/groupa1/resq/entity/File.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.groupa1.resq.entity;

import jakarta.persistence.*;
import lombok.Data;

@Entity
@Data
public class File {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String fileName;

private String fileType;

private String fileUrl;

@OneToOne(mappedBy = "file")
private Resource resource;

}
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,10 @@ public class Resource extends BaseEntity {

private BigDecimal latitude;
private BigDecimal longitude;

@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "file_id", referencedColumnName = "id")
private File file;

private EResourceStatus status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.groupa1.resq.repository;

import com.groupa1.resq.entity.File;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface FileRepository extends JpaRepository<File, Long> {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.groupa1.resq.request;

import com.groupa1.resq.entity.enums.ESize;
import lombok.Data;

import java.math.BigDecimal;
Expand All @@ -11,6 +12,6 @@ public class CreateNeedRequest {
private BigDecimal longitude;
private String categoryTreeId;
private Integer quantity;
private String size;
private ESize size;
private Boolean isRecurrent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.groupa1.resq.entity.enums.EGender;
import com.groupa1.resq.entity.enums.ESize;
import com.groupa1.resq.entity.enums.EResourceStatus;
import lombok.Data;
import org.springframework.lang.Nullable;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;

Expand All @@ -16,6 +19,6 @@ public class CreateResourceRequest {
private BigDecimal latitude;
private BigDecimal longitude;
private EGender gender;
private String size;
private ESize size;
private EResourceStatus status; // This field is only for resource update, default is AVAILABLE
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.groupa1.resq.request;

import com.groupa1.resq.entity.enums.ESize;
import lombok.Data;

import java.math.BigDecimal;
Expand All @@ -11,6 +12,6 @@ public class UpdateNeedRequest {
private BigDecimal longitude;
private String categoryTreeId;
private Integer quantity;
private String size;
private ESize size;
private Boolean isRecurent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public Long save(Long userId, CreateNeedRequest createNeedRequest) {
need.setLatitude(createNeedRequest.getLatitude());
need.setQuantity(createNeedRequest.getQuantity());
need.setCategoryTreeId(createNeedRequest.getCategoryTreeId());
need.setSize(ESize.valueOf(createNeedRequest.getSize()));
need.setSize(createNeedRequest.getSize());
need.setStatus(ENeedStatus.NOT_INVOLVED);
need.setIsRecurrent(createNeedRequest.getIsRecurrent());
return needRepository.save(need).getId();
Expand Down Expand Up @@ -105,7 +105,7 @@ public ResponseEntity<String> update (UpdateNeedRequest updateNeedRequest, Long
need.setLatitude(updateNeedRequest.getLatitude());
need.setQuantity(updateNeedRequest.getQuantity());
need.setCategoryTreeId(updateNeedRequest.getCategoryTreeId());
need.setSize(ESize.valueOf(updateNeedRequest.getSize()));
need.setSize(updateNeedRequest.getSize());
need.setIsRecurrent(updateNeedRequest.getIsRecurent());
needRepository.save(need);
return ResponseEntity.ok("Need updated successfully");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.groupa1.resq.service;

import com.groupa1.resq.config.AmazonClient;
import com.groupa1.resq.converter.ResourceConverter;
import com.groupa1.resq.dto.ResourceDto;
import com.groupa1.resq.entity.File;
import com.groupa1.resq.entity.Resource;
import com.groupa1.resq.entity.User;
import com.groupa1.resq.entity.enums.EResourceStatus;
import com.groupa1.resq.entity.enums.ESize;
import com.groupa1.resq.exception.EntityNotFoundException;
import com.groupa1.resq.repository.ResourceRepository;
import com.groupa1.resq.request.CreateResourceRequest;
Expand All @@ -15,6 +16,7 @@
import org.springframework.data.jpa.domain.Specification;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.List;
Expand All @@ -35,7 +37,10 @@ public class ResourceService {
@Autowired
private ResourceConverter resourceConverter;

public ResponseEntity<Object> createResource(CreateResourceRequest createResourceRequest) {
@Autowired
private AmazonClient amazonClient;

public ResponseEntity<Object> createResource(CreateResourceRequest createResourceRequest, MultipartFile file) {
if(createResourceRequest.getSenderId() == null) {
log.error("Sender id is null");
return ResponseEntity.badRequest().body("Sender id is null");
Expand All @@ -56,7 +61,12 @@ public ResponseEntity<Object> createResource(CreateResourceRequest createResourc
resource.setLatitude(createResourceRequest.getLatitude());
resource.setQuantity(createResourceRequest.getQuantity());
resource.setCategoryTreeId(createResourceRequest.getCategoryTreeId());
resource.setSize(ESize.valueOf(createResourceRequest.getSize()));
resource.setSize(createResourceRequest.getSize());
if (file != null && !file.isEmpty()) {
File fileEntity = amazonClient.uploadFile(file);
fileEntity.setResource(resource);
resource.setFile(fileEntity);
}
resource.setStatus(EResourceStatus.AVAILABLE); // default
resource.setGender(createResourceRequest.getGender());
Long resourceId = resourceRepository.save(resource).getId();
Expand All @@ -69,7 +79,7 @@ public ResponseEntity<String> updateResource(CreateResourceRequest createResourc
resource.setLatitude(createResourceRequest.getLatitude());
resource.setLongitude(createResourceRequest.getLongitude());
resource.setCategoryTreeId(createResourceRequest.getCategoryTreeId());
resource.setSize(ESize.valueOf(createResourceRequest.getSize()));
resource.setSize(createResourceRequest.getSize());
resource.setStatus(createResourceRequest.getStatus());
resourceRepository.save(resource);
return ResponseEntity.ok("Resource updated successfully");
Expand Down

0 comments on commit 4c35d75

Please sign in to comment.