본 테스트는 jquery를 이용했습니다.


1. FormData 란

FormData는 <form> 태그의 역할을 수행하는 객체이다.
FormData를 사용하면 반드시 ContentType과 processData를 false로 해주어야 한다.

contentType을 false로 설정해줄 경우 contentType이 자동으로 아래와 같이 설정된다.

multipart/form-data; boundary=----WebKitFormBoundaryzS65BXVvgmggfL5A

1) FormData 생성

var formData = new FormData();  or new FormData(form);

2) Form에 데이터 삽입

formData.append(key, value); // input태그를 통해 데이터를 삽입하는 방식과 동일하다.

2. 예제

1). member.html

<html>
...
        <form id="editForm">
            <input name="id" value="2020"/>
            <input type="file" name="file"/>
            <button id="saveBtn" type="button">저장</button>
        </form>
...
</html>

2). member.js

$(document).ready(function () {
    var editForm = $("#editForm");

    $("#saveBtn").click(function () {
        var formData = new FormData(editForm[0]);
        formData.append("name", "kim");
        formData.append("description", "how are you?");

        $.ajax({
            method: "POST",
            data: formData,
            dataType: 'json',
            processData: false,
            contentType: false,
            success: function () {
                console.log("completed!");
            },
            error: function () {
                alert("failed! ")
            }
        });
    });
});

formData.append(key, value)를 통해 input 태그없이 추가적으로 데이터를 삽입할 수 있다.

3). MemberTO

public class MemberTO {

    private int id;
    private String name;
    private String description;

    private MultipartFile file;

//getter,setter,toStrng 생략
}

4). TestController

@Controller
public class TestController{
   @GetMapping(value = "/member")
    public String memberPage() {
        return "page/member";
    }

    @ResponseBody
    @PostMapping(value = "/member")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void memberData(MemberTO member) {

        logger.info("[MYTEST] {} {}", member, member.getFile().getOriginalFilename());
    }

}

5). 결과

5-1) form Data

5-2) log

[MYTEST] Test{id=2020, name=kim, description=how are you?} 2.png

 

출처 : https://developer.mozilla.org/ko/docs/Web/API/FormData/FormData

본 예제는 jquery를 이용해 구현하였습니다.

1. fileUpload.html

<html>
...

    <input type="file" id="files" multiple/>
    <button id="saveBtn" type="button">저장</button>

...
</html>

2. fileUpload.js

$(document).ready(function () {

    $("#saveBtn").click(function () {
    
        var formData = new FormData();
        //formData란 <form> 태그를 객체화한 것을 의미한다.
        //formData.append(key, value)를 이용해 데이터를 삽입할 수 있다.
        //form 태그 내에 input 태그를 사용한 것과 동일하다.
        
        var files = $("#files")[0].files; //선택한 파일리스트를 가져온다.

        for (var index = 0; index < files.length; index++) {
            formData.append(`files[${index}].file`, files[index]);
            formData.append(`files[${index}].id`, index + 1);
        }
        //formData의 file key값을 files[0,1..].file 형식으로 지정한다.

        $.ajax({
            type: "POST",
            data: formData,
            dataType: 'json',
            processData: false,
            contentType: false,
            success: function (data) {
                alert("completed!");
            },
            error : function(){
                alert("failed! ")
            }
        });
    });
});

processData가 false인 경우 formData를 QueryString으로 변환하지 않는다.
contentType이 false인 경우 contentType이 아래와 같이 설정된다.
multipart/form-data; boundary=----WebKitFormBoundaryzS65BXVvgmggfL5A

@Controller
class FileUploadController{
    @GetMapping(value = "/fileUpload")
    public String fileUploadPage() {
        return "page/fileUpload";
    }

    @ResponseBody
    @PostMapping(value = "/fileUpload")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void fileUpload(FileFormTO fileFormTO) {

        fileFormTO.getFiles().forEach(fileData -> {
            logger.info("{} {}", fileData, fileData.getFile().getOriginalFilename());
        });
        //file save Logic
    }
}

3. FileTO

public class FileTO {

    private Integer id;
    private boolean deleted = false;
    private MultipartFile file;
    
    
    //setter, getter, toString 생략

}

파일 객체를 정의한다.

4. FileFormTO

public class FileFormTO {

    private List<FileTO> files;

	//setter, getter 생략
}

form데이터를 객체 단위로 전달받으려면 위와 같이 한번 더 객체로 감싸야한다. 

5. FileUploadController

@Controller
class FileUploadController{
    @GetMapping(value = "/fileUpload")
    public String fileUplaodPage() {
        return "page/fileUpload";
    }

    @ResponseBody
    @PostMapping(value = "/fileUpload")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void fileUpload(FileFormTO fileFormTO) {

        fileFormTO.getFiles().forEach(fileData -> {
            logger.info("{} {}", fileData, fileData.getFile().getOriginalFilename());
        });
    }
}

6. 테스트

이미지 3개 등록

 

파일의 다양한 정보를 하나의 객체로 묶어 서버에 전달할 때, 위 방법을 사용하면 매우 유용하다. 

+ Recent posts