2020. 12. 30. 00:34ㆍ프로젝트/Salle(살래) 중고거래 웹
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;
'프로젝트 > Salle(살래) 중고거래 웹' 카테고리의 다른 글
5. 판매 게시글 페이지 - (2) 구현 (0) | 2021.01.03 |
---|---|
5. 판매 상품 게시글 페이지 (1) - 구상 (0) | 2020.12.30 |
[Salle] 중간점검 - 프로젝트 기한 세우기 (0) | 2020.12.28 |
[Salle] 4. 판매하기 페이지 (5) - 1차 완성 (0) | 2020.12.23 |
[Salle] 4. 판매하기 페이지 (4) - img파일 DB 저장 (0) | 2020.12.22 |