[22/01/20] ajax formdata로 파일&데이터 보내기

Que Lin·2022년 1월 20일
0

1day 1commit

목록 보기
13/63

오늘 종일 나를 괴롭혔던 이놈
415, 400, 500의 오류를 맛보게 해주었다.
결국 근본적인 이유는
json과 파일을 같이 보내려고 했던 시도가 잘 안됐던 것 같다.

<오류가 났던 코드>

 const updateData = JSON.stringify({
            memberId : memberId,
            memberName : memberName,
            memberEmail : memberEmail,
            memberPassword : memberPassword,
            memberPhone : memberPhone,
            }
        );
        const formData = new FormData();
        for (let i = 0; i < memberProfile.length; i++) {
            formData.append('memberProfile', memberProfile[i]);
        }
        formData.append('updateData', updateData);
        formData.append('memberProfile', memberProfile);

인터넷에 구글링을 해보다가 이렇게 할 수 있겠구나 싶어서 적용 해 봤지만 400, 500 오류가 떴다. 검색해 보니 파일+제이슨스트링 형식이 contentType이 안맞아서 그런 것 같다. 요 formdata를 나중에 더 공부해보면 왜 그런지 알 수 있을까?

결국 해결방법은 다 지우고 form에 id를 줘서 formdata에 보내면 됐던 것이다!

<해결 코드>
update html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <meta charset="UTF-8">
    <title>update</title>
</head>
<body>
<form id="updateForm" th:object="${member}" enctype="multipart/form-data">
    <input type="hidden" th:field="*{memberId}">
    <input type="text" th:field="*{memberName}" placeholder="이름" readonly>
    <input type="text" th:field="*{memberEmail}" placeholder="이메일" readonly>
    <input type="password" th:field="*{memberPassword}" placeholder="비밀번호입력">
    <input type="text" th:field="*{memberPhone}" placeholder="변경할 전화번호" readonly>
    <label for="memberProfile">프로필 사진 선택</label>
    <input th:class="form-control" type="file" id="memberProfile" name="memberProfile">
    <input type="button" value="수정(put)" th:onclick="memberUpdate()">
</form>
</body>

<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script>
    const memberUpdate = () => {
        const memberId = document.getElementById('memberId').value;
        const memberName = document.querySelector('#memberName').value;
        const memberEmail = $('#memberEmail').val();
        const memberPassword = $('#memberPassword').val();
        const memberPhone = $('#memberPhone').val();
        const memberProfile = document.getElementById('memberProfile').value;
        console.log(memberId,memberName,memberEmail,memberPassword,memberPhone,memberProfile);
        const reqUrl = "/member/" +memberId;

        const data = $('#updateForm')[0];
        const formData = new FormData(data);


        const pwDB = "[[${member.memberPassword}]]";
        if(pwDB == memberPassword){
            $.ajax({
                type : 'put',
                cache: false,
                contentType : false,
                processData : false,
                data : formData,
                url : reqUrl,
                success : function (){
                    location.reload()
                },error : function (){
                    alert("요청실패")
                }
            })}
        else {
            alert('비밀번호가 틀렸습니다.');
        }
    };

</script>
</html>

Controller

 @PutMapping("/{memberId}")
    public ResponseEntity update(@ModelAttribute MemberUpdateDTO memberUpdateDTO)
            throws IllegalStateException, IOException {
        System.out.println("받아온 것"+ memberUpdateDTO);
       ms.update(memberUpdateDTO);
        return new ResponseEntity(HttpStatus.OK);
    }

그리고 Controller에서 formData는 @RequestBody 로 받아오면 안된다고 한다. json 형식으로 받아올때만 @RequestBody를 쓰고 @ModelAttribute로 받아와야 한다. @RequestBody를 쓰면 이제 415 오류가 뜬다.

serviceImpl - 파일을 파일명으로 변환해줘야겠지요?

 @Override
    public void update(MemberUpdateDTO memberUpdateDTO) throws IllegalStateException, IOException {
        // 프로필 사진 저장하기 파일 -> 이름
        MultipartFile m_file = memberUpdateDTO.getMemberProfile();
        String m_filename = m_file.getOriginalFilename();
        m_filename = System.currentTimeMillis() + "-" + m_filename;
        // 파일 저장하기
        String savePath = "D:\\development_Phl\\source\\springboot\\MemberBoardProject\\src\\main\\resources\\member_uploadfile\\"+m_filename;
        if(!m_file.isEmpty()) {
            m_file.transferTo(new File(savePath));
        }
        memberUpdateDTO.setMemberProfileName(m_filename);

        MemberEntity memberEntity = MemberEntity.toMemberUpdateEntity(memberUpdateDTO);
        mr.save(memberEntity);
    }

UpdateDTO

@Data
@AllArgsConstructor
@NoArgsConstructor
public class MemberUpdateDTO {
    private Long memberId;
    private String memberEmail;
    private String memberPassword;
    private String memberName;
    private String memberPhone;
    private MultipartFile memberProfile;
    private String memberProfileName;

}

Entity - 아이디가 같은 곳에 다시 덮어써서 저장하면 끝!

@Entity
@Getter
@Setter
@Table(name = "member_table")
public class MemberEntity extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "member_id")
    private Long id;

    @Column
    private String memberEmail;

    @OneToMany(mappedBy = "memberEntity", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private List<BoardEntity> boardEntityList = new ArrayList<>();

    @OneToMany(mappedBy = "memberEntity", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    private List<CommentEntity> commentEntityList = new ArrayList<>();

    @Column
    private String memberPassword;

    @Column
    private String memberName;

    @Column
    private String memberPhone;

    @Column
    private String memberProfileName;

    public static MemberEntity toMemberEntitySave(MemberSaveDTO memberSaveDTO){
        MemberEntity memberEntity = new MemberEntity();

        memberEntity.setMemberEmail(memberSaveDTO.getMemberEmail());
        memberEntity.setMemberPhone(memberSaveDTO.getMemberPhone());
        memberEntity.setMemberName(memberSaveDTO.getMemberName());
        memberEntity.setMemberPassword(memberSaveDTO.getMemberPassword());
        memberEntity.setMemberProfileName(memberSaveDTO.getMemberProfileName());

        return memberEntity;
    }


    public static MemberEntity toMemberUpdateEntity(MemberUpdateDTO memberUpdateDTO){
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setId(memberUpdateDTO.getMemberId());
        memberEntity.setMemberName(memberUpdateDTO.getMemberName());
        memberEntity.setMemberEmail(memberUpdateDTO.getMemberEmail());
        memberEntity.setMemberPassword(memberUpdateDTO.getMemberPassword());
        memberEntity.setMemberPhone(memberUpdateDTO.getMemberPhone());
        memberEntity.setMemberProfileName(memberUpdateDTO.getMemberProfileName());

        return memberEntity;
    }
profile
1일 1커밋 1일 1벨로그!

0개의 댓글