4. 판매하기 페이지 (6) - IMG 단일파일 여러 장 업로드 성공

2020. 12. 30. 00:34프로젝트/Salle(살래) 중고거래 웹

728x90

2020.12.23 1차 완성이란 타이틀로 업로드한 게시글이 있는데 오늘에야 판매하기 페이지 1차 완성할 수 있었다. 단일 파일을 여러 개 업로드 하는 기능이 이렇게 어려울 줄 몰랐다. 그래서 상품 판매 게시글 페이지 구상은 따로 업로드할 예정이고 본 글에선 해당 기능 구현이 어떤 과정을 거쳐 이제서야 어떻게 완성을 시켰는지 자세히 다루겠다.

 

구글링 해보면 사용자가 여러 파일을 업로드 할 경우 <input type="file" multiple /> 형태로 태그를 만들고 <form:form enctype="multipart/form-data">로 폼 데이터가 submit 될 때 파일 데이터가 Controller에서 받아줄 수 있도록 인코딩 되는 형식을 설정해주었다. 또는 <input type="file"/>을 여러개 만들어 첨부파일 버튼이 업로드 파일 수 만큼 노출되도록 구현해줬다. 그러나 내가 원하는 것은 하나의 버튼으로 판매상품 이미지 파일들을 하나씩 업로드하고 사용자가 업로드 할 이미지를 볼 수 있도록 화면에 띄우는 것이었다. 검색이 아직 어려운 것도 있지만, 일치하는 레퍼런스 코드를 구하기 힘들었다.

 

그래서 사용한 방법은 업로드한 파일들을 담아주는 역할을 하는 Javascript FormData() 객체와 서버로 전달해주는 jQuery - ajax를 사용했다. Spring boot 기반이기 때문에 사용자로부터 POST 방식 URI 요청이 왔을 때 MVC Controller에서 ajax가 전달한 data: formData를 HttpServletRequest로 받아준 다음 File() 객체로 읽을 수 있도록 MultipartHttpServletRequest로 형 변환해줬다. 그리고 나서 File()을 상속받는 MultipartFile의 getFile()로 전달받은 이미지 파일을 File 타입으로 받아 파일정보는 DB로 저장하고 실제 파일은 로컬 폴더에 저장해줬다.


코드

(View) sell.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
 
 <form:form id="frm" action="sellproduct/done" method="post" enctype="multipart/form-data">
    
    <section class="pr_img">
          <p>    
            <label for="img"><h2>상품 이미지</h2></label>
        </p>
        <div id="pr_img">
            <input type="file" id="img" name="pr_img_files"/>            
        
        </div>
        <%=request.getRealPath("/") %>
        <input id="upload" type="button" value="업로드" onclick="fileUpload()"/>
    </section>
 
</form>
 
 
  <script>
    
    var img_count = 1;
    var formData = new FormData();
        
    //pr_img
    //input 파일첨부 버튼 클릭하면 실행되는 change 메서드
    $("#img").change(function fileadd() {
        var reader = new FileReader;
    //이미지 파일 정보와 화면출력을 위해 <img> 태그를 변수로 만듦
        var str = "<img id='img_"+(img_count)+"' src=''/>";
    //파일 경로에 넣기 위해 String으로 변환시켜줌
        var img_count_string = img_count.toString();
        
    //jQuery append 메서드를 사용해 <div id="pr_img"> 안에 <img> 태그 변수를 추가해줌
        $("#pr_img").append(str);
    
    //formdata에 append
    
    //onload는 파일이 업로드 완료된 시점에 function을 발생시키는 메서드
    //<img src=""> 사용자가 업로드한 이미지 파일 경로를 src로 저장해줌(data.target.result) 
        reader.onload = function(data) {
    //태그 안의 속성을 입력할 수 있는 jQuery attr 메서드를 사용 
            $('#img_' + img_count_string).attr('src', data.target.result).width(150);
        };
        
    //화면에 이미지를 출력해주는 FileReader 객체 인스턴스 reader.readAsDataURL();
    //this.files는 <input type="file">을 통해 업로드한 파일의 정보를 저장하고 있는 배열이다.
    //첨부하기 1회당 file 하나만 업로드해서 <img_0,1,2...>에 각각의 파일들을
    //할당시켜줄 것이기 때문에 files[0]로 index 고정    
 
        reader.readAsDataURL(this.files[0]);
    
    //ajax로 전달할 files를 formData에 담는다.  
        formData.append('pr_img_' + img_count_string, this.files[0]);
 
    img_count++;
            
    });
 
 
    //업로드 버튼 클릭
    function fileUpload() {
        
        $.ajax({
            url:"/sellproduct/ajax",
               type: 'POST',
            data: formData,
                processData: false,
                contentType: false,
                success: function(data) {
                    console.log('jQuery ajax form submit success');
                    }
            }); //end ajax
            
        formData.delete;
    }
 
  </script>
cs

 

(Controller) SellProductController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
@Controller
public class SellProductController {
    
    @Autowired
    ProductService productService;
    
    @Autowired
    UuidImgname uuidImgname;
 
    @RequestMapping(value = "/sellproduct", method = RequestMethod.GET)
    public String sellAttempt(Model model) {
 
        model.addAttribute("product"new Product());    
        return "sell";
    }
    
    @RequestMapping(value = "/sellproduct/done", method = RequestMethod.POST)
    public String sellHandle(@ModelAttribute @Valid Product product, Errors errors,
            HttpSession httpSession) throws Exception {
        
        //파일 업로드 작업 수행(destination에 파일을 보내줌)
 
        new SellProductValidation().validate(product, errors);
        
        if (errors.hasErrors()) {
            return "redirect:/sellproduct";
        }
        
        Member member = (Member) httpSession.getAttribute("member");
        product.setEmail(member.getEmail());
        
        //ajax로 받은 img_file 정보를 넘겨줌 
        product.setPr_img_1(product_file.getPr_img_1());
        product.setPr_img_2(product_file.getPr_img_2());
        product.setPr_img_3(product_file.getPr_img_3());
        product.setPr_img_4(product_file.getPr_img_4());
        product.setPr_img_5(product_file.getPr_img_5());
        
        productService.registerProduct(product);
 
        return "home";
    }
    
    //상품등록 이미지파일 업로드
    Product product_file = new Product();
    
    @RequestMapping(value= "/sellproduct/ajax", method= RequestMethod.POST)
    public void ajax(HttpServletRequest req) throws Exception {
        
        //실행확인
        System.out.println("ajax_contorller_turnedOn");
        
        //formdata를 받은 req를 multipartfile로 타입 변환해줌
        MultipartHttpServletRequest multi = (MultipartHttpServletRequest) req;
        Iterator<String> iterator = multi.getFileNames();     
        MultipartFile multipartFile = null;
        
        
        int reps = 0;
        
        while(iterator.hasNext()) {
            
            System.out.println(reps);
            
            multipartFile = multi.getFile(iterator.next());
            
            String filepath = multipartFile.getOriginalFilename();
            String filename = uuidImgname.makeFilename(filepath);
 
            //파일 로컬폴더에 저장
            multipartFile.transferTo(new File("C:\\Users\\klyhy\\git\\salle_eclipse_v1\\demo\\src\\main\\webapp\\201229_"
                    + filename));
 
            switch(reps) {
            case 0
                product_file.setPr_img_1(filename);
                break;
            case 1
                product_file.setPr_img_2(filename);
                break;
            case 2
                product_file.setPr_img_3(filename);
                break;
            case 3
                product_file.setPr_img_4(filename);
                break;
            case 4
                product_file.setPr_img_5(filename);
                break;
            }
            
            reps++;
        }
    }
cs

이슈

  • formData가 URI 변화에도 리셋되지 않음 → 업로드 버튼 클릭시 전송완료 되면 formData = null;