Skip to content

Commit

Permalink
feat : image file 업로드 (#16)
Browse files Browse the repository at this point in the history
* refactor : CardService 메서드 정리

* refactor : GroupService 역할 분리

* feat : ImageFileService

* refactor : service 코드 도메인으로 이동

* refactor : fileService 제거

* refactor : CardService가 ImageFile을 다루도록 수정

* refactor : CardService 리팩토링

* refactor : Profile Image 요청 루트 경로 수정

* feat : resource handler에 utf8 decode resolver 추가
  • Loading branch information
ecsimsw committed Mar 4, 2022
1 parent 6c68fcf commit b48b31c
Show file tree
Hide file tree
Showing 31 changed files with 265 additions and 274 deletions.
File renamed without changes
2 changes: 1 addition & 1 deletion page/src/components/ProfileCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const ProfileCard: FC<Props> = ({ name, gender, email, job, imageUrl }) => {
return (
<ProfileCardStyle>
<div className="profile-card">
<img src={`http://localhost:8080${imageUrl}`} />
<img src={`http://localhost:8080/`+`${imageUrl}`} />
<div className="right">
<div className="name">
{name} | {gender}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.giggle.samehere;

import com.giggle.samehere.card.exception.CardException;
import com.giggle.samehere.file.exception.FileUploadException;
import com.giggle.samehere.card.exception.FileUploadException;
import com.giggle.samehere.group.exception.GroupException;
import com.giggle.samehere.item.exception.ItemException;
import org.slf4j.Logger;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
import com.giggle.samehere.group.domain.GroupRepository;
import com.giggle.samehere.item.domain.Item;
import com.giggle.samehere.item.domain.ItemRepository;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@SpringBootApplication
public class SameHereApplication {

Expand Down Expand Up @@ -44,4 +45,4 @@ public void setUp() {
itemRepository.save(Item.shortAnswerQuestion("깃허브"));
itemRepository.save(Item.shortAnswerQuestion("링크드인"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,89 +4,103 @@
import com.giggle.samehere.card.domain.CardItem;
import com.giggle.samehere.card.domain.CardItemRepository;
import com.giggle.samehere.card.domain.CardRepository;
import com.giggle.samehere.card.dto.CardItemResponse;
import com.giggle.samehere.card.domain.ImageFile;
import com.giggle.samehere.card.dto.CardRequest;
import com.giggle.samehere.card.dto.CardResponse;
import com.giggle.samehere.card.dto.CardSimpleResponse;
import com.giggle.samehere.card.exception.CardException;
import com.giggle.samehere.group.application.GroupService;
import com.giggle.samehere.card.exception.FileUploadException;
import com.giggle.samehere.group.domain.CardGroup;
import com.giggle.samehere.group.domain.CardGroupRepository;
import com.giggle.samehere.group.dto.GroupResponse;
import com.giggle.samehere.group.domain.Group;
import com.giggle.samehere.group.domain.GroupRepository;
import com.giggle.samehere.group.exception.GroupException;
import com.giggle.samehere.item.domain.Item;
import com.giggle.samehere.item.domain.ItemRepository;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

@Service
public class CardService {

private final GroupService groupService;
@Value("${cards.profile.image.upload.folder}")
private String IMAGE_FOLDER_PATH;

@Value("${cards.profile.image.default.name}")
private String DEFAULT_PROFILE_IMAGE_FILE_NAME;

private final CardRepository cardRepository;
private final ItemRepository itemRepository;
private final CardItemRepository cardItemRepository;
private final GroupRepository groupRepository;
private final CardGroupRepository cardGroupRepository;
private final ItemRepository itemRepository;

public CardService(
GroupService groupService,
CardRepository cardRepository,
ItemRepository itemRepository,
CardItemRepository cardItemRepository,
CardGroupRepository cardGroupRepository,
ItemRepository itemRepository
GroupRepository groupRepository,
CardGroupRepository cardGroupRepository
) {
this.groupService = groupService;
this.cardRepository = cardRepository;
this.itemRepository = itemRepository;
this.cardItemRepository = cardItemRepository;
this.groupRepository = groupRepository;
this.cardGroupRepository = cardGroupRepository;
this.itemRepository = itemRepository;
}

@Transactional
public CardResponse create(CardRequest request, String imageFile) {
final Card card = request.toCard(imageFile);
cardRepository.save(card);
return CardResponse.of(card, Collections.emptyList(), Collections.emptyList());
public CardResponse create(CardRequest request, MultipartFile multipartFile) {
try {
final ImageFile imageFile = ImageFile.save(IMAGE_FOLDER_PATH, multipartFile);
final Card card = request.toCard(imageFile);
cardRepository.save(card);
return cardResponse(card);
} catch (FileUploadException fue) {
return create(request);
}
}

@Transactional
public CardResponse createInGroup(Long groupId, CardRequest request, String imageFile) {
public CardResponse create(CardRequest request) {
final ImageFile imageFile = ImageFile.pathOf(IMAGE_FOLDER_PATH + DEFAULT_PROFILE_IMAGE_FILE_NAME);
final Card card = request.toCard(imageFile);
cardRepository.save(card);
final List<GroupResponse> groupResponses = groupService.enter(groupId, card);
return CardResponse.of(card, Collections.emptyList(), groupResponses);
return cardResponse(card);
}

@Transactional(readOnly = true)
public CardResponse findById(Long id) {
final Card card = getCard(id);
final List<CardItem> cardItems = cardItemRepository.findAllByCardId(card.getId());
final List<GroupResponse> groups = groupService.findAllByCard(card);
return CardResponse.of(card, CardItemResponse.listOf(cardItems), groups);
@Transactional
public CardResponse enterInGroup(Long cardId, Long groupId) {
final Card card = getCard(cardId);
final Group group = groupRepository.findById(groupId).orElseThrow(IllegalArgumentException::new);
checkDuplicated(card, group);
cardGroupRepository.save(new CardGroup(card, group));
return cardResponse(card);
}

@Transactional(readOnly = true)
public List<CardSimpleResponse> findAllCardsByGroup(Long groupId) {
final List<CardGroup> cardGroups = cardGroupRepository.findAllByGroupId(groupId);
final List<Card> cardsInGroup = cardGroups.stream().map(CardGroup::getCard).collect(Collectors.toList());
return CardSimpleResponse.listOf(cardsInGroup);
private void checkDuplicated(Card card, Group enteringGroup) {
cardGroupRepository.findAllByCard(card).stream()
.filter(it -> it.isGroup(enteringGroup))
.findAny()
.ifPresent(it -> {
throw new GroupException("이미 가입된 카드입니다.");
});
}

@Transactional
public CardResponse update(Long id, CardRequest request) {
final Card card = getCard(id);
card.update(request.toCard(card.getPhotosImagePath()));
final Card oldCard = getCard(id);
final Card newCard = request.toCard(oldCard.getImagePath());
oldCard.update(newCard);

final List<CardItem> cardItems = getRequestCardItems(request, id);
cardItems.forEach(CardItem::validateAnswer);

cardItemRepository.deleteAllByCardId(id);
cardItemRepository.saveAll(cardItems);

final List<GroupResponse> groups = groupService.findAllByCard(card);
return CardResponse.of(card, CardItemResponse.listOf(cardItems), groups);
return cardResponse(oldCard);
}

private List<CardItem> getRequestCardItems(CardRequest request, Long cardId) {
Expand All @@ -95,12 +109,17 @@ private List<CardItem> getRequestCardItems(CardRequest request, Long cardId) {
.collect(Collectors.toList());
}

@Transactional
public CardResponse enterInGroup(Long cardId, Long groupId) {
final Card card = getCard(cardId);
final List<GroupResponse> groupResponses = groupService.enter(groupId, card);
final List<CardItem> cardItems = cardItemRepository.findAllByCardId(card.getId());
return CardResponse.of(card, CardItemResponse.listOf(cardItems), groupResponses);
@Transactional(readOnly = true)
public CardResponse findById(Long id) {
final Card card = getCard(id);
return cardResponse(card);
}

@Transactional(readOnly = true)
public List<CardSimpleResponse> findAllCardsByGroup(Long groupId) {
final List<CardGroup> cardGroups = cardGroupRepository.findAllByGroupId(groupId);
final List<Card> cardsInGroup = cardGroups.stream().map(CardGroup::getCard).collect(Collectors.toList());
return CardSimpleResponse.listOf(cardsInGroup);
}

private Item getItem(Long itemId) {
Expand All @@ -110,4 +129,12 @@ private Item getItem(Long itemId) {
private Card getCard(Long targetId) {
return cardRepository.findById(targetId).orElseThrow(() -> new CardException("존재하지 않는 카드입니다."));
}

private CardResponse cardResponse(Card card) {
final List<CardItem> cardItems = cardItemRepository.findAllByCardId(card.getId());
final List<Group> groups = cardGroupRepository.findAllByCard(card).stream()
.map(CardGroup::getGroup)
.collect(Collectors.toList());
return CardResponse.of(card, cardItems, groups);
}
}
20 changes: 7 additions & 13 deletions server/src/main/java/com/giggle/samehere/card/domain/Card.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import org.springframework.data.annotation.Transient;

@Entity
public class Card {
Expand All @@ -15,17 +14,18 @@ public class Card {
private String email;
private String gender;
private String profession;
private String image;
private String imagePath;
private String password;

public Card() {}
public Card() {
}

public Card(String name, String email, String gender, String profession, String image, String password) {
public Card(String name, String email, String gender, String profession, String imagePath, String password) {
this.name = name;
this.email = email;
this.gender = gender;
this.profession = profession;
this.image = image;
this.imagePath = imagePath;
this.password = password;
}

Expand Down Expand Up @@ -58,14 +58,8 @@ public String getProfession() {
return profession;
}

public String getImage() {
return image;
}

// TODO :: 저장 경로 수정
public String getPhotosImagePath() {
if (image == null || id == null) return null;
return "/card-photos/" + id + "/" + image;
public String getImagePath() {
return imagePath;
}

public String getPassword() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.giggle.samehere.card.domain;

import com.giggle.samehere.item.domain.Item;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;

import javax.persistence.*;

@Entity
public class CardItem {
Expand All @@ -19,15 +16,13 @@ public class CardItem {
private Item item;
private String answer;

protected CardItem() {}
protected CardItem() {
}

public CardItem(Long cardId, Item item, String answer) {
this.cardId = cardId;
this.item = item;
this.answer = answer;
}

public void validateAnswer() {
item.validateAnswer(answer);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.giggle.samehere.card.domain;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface CardItemRepository extends JpaRepository<CardItem, Long> {

List<CardItem> findAllByCardId(Long cardId);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.giggle.samehere.card.domain;

import com.giggle.samehere.card.exception.FileUploadException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

public class ImageFile {

private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd.HH:mm:ss");

private final Path filePath;

private ImageFile(Path filePath) {
this.filePath = filePath;
}

public static ImageFile pathOf(String filePath) {
return new ImageFile(Path.of(filePath));
}

public static ImageFile save(Path directoryPath, MultipartFile multipartFile) {
try (InputStream inputStream = multipartFile.getInputStream()) {
if (!Files.exists(directoryPath)) {
Files.createDirectories(directoryPath);
}
final Path filePath = filePath(directoryPath, multipartFile);
Files.copy(inputStream, filePath, StandardCopyOption.REPLACE_EXISTING);
return new ImageFile(filePath);
} catch (Exception e) {
e.printStackTrace();
throw new FileUploadException();
}
}

public static ImageFile save(String directoryPath, MultipartFile multipartFile) {
return save(Path.of(directoryPath), multipartFile);
}

private static Path filePath(Path directoryPath, MultipartFile multipartFile) {
final String prefix = LocalDateTime.now().format(DATE_TIME_FORMATTER) + ":";
final String fileName = prefix+StringUtils.cleanPath(multipartFile.getOriginalFilename());
final Path path = directoryPath.resolve(fileName);
return uniquePath(path);
}

private static Path uniquePath(Path path) {
if (Files.exists(path)) {
return uniquePath(Path.of(path + UUID.randomUUID().toString().substring(0, 5)));
}
return path;
}

public Path path() {
return filePath;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public CardItemResponse(String itemName, String value) {
}

public static List<CardItemResponse> listOf(List<CardItem> cardItems) {
return cardItems.stream().map(it-> of(it)).collect(Collectors.toList());
return cardItems.stream().map(it -> of(it)).collect(Collectors.toList());
}

public static CardItemResponse of(CardItem cardItem) {
Expand Down
Loading

0 comments on commit b48b31c

Please sign in to comment.