JSP를 활용하여 파일 업로드를 하고 조회수와 다운수를 실시간으로 업데이트 시켜주는 기능을 구현하려고 하였다.
기존 JSP의 동작은 새로고침이 되야 데이터가 업데이트 되는 방식이였다. 하지만 나는 SPA처럼 다운 수 부분만 업데이트 시켜주고 싶었다.
로직은 "다운로드 버튼 클릭" -> "ajax에서 FileDownload 서블릿 url로 요청" -> FileDownload 서블릿에서 "파일다운로직, ajax response로 업데이트 된 다운 수 전달"
로 생각하여 개발을 진행하였다.
하지만 ajax 응답이 계속해서 오지 않았고, 성공 시 응답이 오더라도 file안의 data가 byte값으로 찍혔다.
이를 해결하기 위해 여러명이 머리를 싸매서 고민했고, 정답을 알아냈다.
일단은 간단한 UI와 파일들을 먼저 보자.
UI에서 보시다시피 다운로드 버튼을 클릭하면 파일이 다운로드 되고, 다운 수가 실시간으로 Update 되게 해주고 싶었다.
도전해봤던 방법
1. FileDownLoader.java에서 JSONObject로 데이터를 받아서 Printwriter를 이용하여 클라이언트로 Json양식의 response를 보내준다. (실패)
- 응답이 원하는 값(업데이트 된 카운트 수)이 아니라 다운로드 받는 파일 내용이 byte 형식으로 나왔다.
고민을 하다가 알아낸 결론!
FileDownLoader.java 에서 이미 resp.setHeader를 이용하여 응답 값이 넘어가는게 아닐까?
// 다운로드 창(다이얼로그)
resp.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";");
resp.setHeader("Content-Transfer-Encoding", "binary;");
resp.setHeader("Content-Length", "" + f.length());
resp.setHeader("Pragma", "no-cache;");
resp.setHeader("Expires", "-1;");
그러면 다운로드 수 카운트를 보내는 response를 다른 서블릿으로 만들어서 해결하면 어떨까?
하는 생각에 downUp.java 서블릿 파일을 추가하여서 개발을 하였고,
다운로드 버튼을 클릭하였을 때 2개의 서블릿을 호출하기 위해 onclick("javascript:func1();func2();") 를 하여 2개의 함수를 같이 호출시켜줬다!
파일 다운로드와, 다운로드 수 카운트 업 로직을 따로 서블릿으로 구현하여 동작시키니 ajax의 응답값이 올바르게 올 수 있었다!
문제를 같이 고민하고 해결해준 롯떼의 갓솔지, 갓진광, 갓지훈 등등 스쳐간 많은 사람들에게 감사를!✌✌
fileList.jsp
<%@page import="dto.PdsDto"%>
<%@page import="java.util.List"%>
<%@page import="dao.PdsDao"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
PdsDao dao = PdsDao.getInstance();
List<PdsDto> list = dao.getPdslist();
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<title>pdslist</title>
<style type="text/css">
td {
text-align: center;
}
</style>
</head>
<body>
<h2>자료실</h2>
<div align="center">
<table border="1">
<col width="50">
<col width="100">
<col width="400">
<col width="100">
<col width="100">
<col width="100">
<col width="100">
<tr>
<th>번호</th>
<th>작성자</th>
<th>제목</th>
<th>다운로드</th>
<th>조회수</th>
<th>다운수</th>
<th>작성일</th>
</tr>
<%
for (int i = 0; i < list.size(); i++) {
PdsDto pds = list.get(i);
%>
<tr>
<th><%=i + 1%></th>
<td><%=pds.getId()%></td>
<td><a href="pdsdetail.jsp?seq=<%=pds.getSeq()%>"> <%=pds.getTitle()%>
</a></td>
<td><input type="button" name="btndown" value="다운로드"
onclick="javascript:filedownload('<%=pds.getNewfilename()%>', <%=pds.getSeq()%>); fn2(<%=pds.getSeq() %>);">
</td>
<td><%=pds.getReadcount()%></td>
<td id="id<%=pds.getSeq() %>"><%=pds.getDowncount()%></td>
<td><%=pds.getRegdate()%></td>
</tr>
<%
}
%>
</table>
<br> <a href="pdswrite.jsp">자료올리기</a>
</div>
<script type="text/javascript">
function fn2(seq){
$.ajax({
url : "downup?seq=" + seq,
type: "get",
datatype: "json",
success : function(data){
console.log(data.msg);
$('#id'+seq).text(data.msg);
},
error: function(){
alert('error');
}
})
}
function filedownload(newfilename, seq){
location.href = "filedown?newfilename=" + newfilename + "&seq=" + seq;
}
</script>
</body>
</html>
// 갓솔지, 갓진광 ,갓지훈,은성!
FileDownLoader.java
- 파일 다운로드 하는 Servlet
package util;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.jasper.tagplugins.jstl.core.Out;
import dao.PdsDao;
import dto.PdsDto;
import net.sf.json.JSONObject;
@WebServlet("/filedown")
public class FileDownLoader extends HttpServlet {
ServletConfig mConfig = null;
final int BUFFER_SIZE = 8192;
@Override // 업로드한 경로를 취득하기 위해서
public void init(ServletConfig config) throws ServletException {
mConfig = config;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String newfilename = req.getParameter("newfilename");
int seq = Integer.parseInt(req.getParameter("seq"));
// downcount를 증가
PdsDao dao = PdsDao.getInstance();
PdsDto dto = dao.getPds(seq); // 원본파일명
String filename = dto.getFilename(); // 원본파일명
BufferedOutputStream out = new BufferedOutputStream(resp.getOutputStream());
// path
// tomcat
String path = mConfig.getServletContext().getRealPath("/upload");
// 폴더
// String path = "d:\\tmp";
path = path + "\\" + newfilename;
File f = new File(path);
// 다운로드 창(다이얼로그)
resp.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\";");
resp.setHeader("Content-Transfer-Encoding", "binary;");
resp.setHeader("Content-Length", "" + f.length());
resp.setHeader("Pragma", "no-cache;");
resp.setHeader("Expires", "-1;");
// 파일 생성 및 기입
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
byte buffer[] = new byte[BUFFER_SIZE];
int read = 0;
while ((read = bis.read(buffer)) != -1) {
out.write(buffer, 0, read); // 실제 다운로드 부분
}
bis.close();
out.flush();
}
}
downUp.java
- 다운로드 카운트 업데이트 시켜주는 Servlet
package util;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import dao.PdsDao;
import dto.PdsDto;
import net.sf.json.JSONObject;
@WebServlet("/downup")
public class downup extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
int seq = Integer.parseInt(req.getParameter("seq"));
PdsDao dao = PdsDao.getInstance();
dao.upDownCount(seq);
PdsDto dto = dao.getPds(seq); // 원본파일명
System.out.println(dto.getDowncount());
JSONObject obj = new JSONObject();
obj.put("msg", dto.getDowncount());
System.out.println(obj);
resp.setContentType("application/x-json; charset=utf-8");
resp.getWriter().print(obj);
// PrintWriter out = resp.getWriter();
// System.out.println(dto.getDowncount());
// out.print(obj);
}
}
'개념공부 > BackEnd' 카테고리의 다른 글
[Django linux-redhat 배포 시] mysqlclient 2.2.4 ver 설치 에러 subprocess-excited-with-error / mysql-devel 설치 시 mariadb-devel로 인식되는 오류 해결 (0) | 2024.02.20 |
---|---|
Web의 변천사 (HTML -> Servlet -> JSP -> MVC -> Spring) (0) | 2022.07.05 |
스레드와 메모리구조 (0) | 2022.06.21 |
[REST] RESTFul 설정 순서 (0) | 2021.10.29 |
댓글