<form action="upload" method="post" enctype="multipart/form-data">
- 파일 업로드 처리를 위한 환경설정 방법
commons-fileupload 라이브러리를 프로젝트에 빌드 처리 (메이븐 : pom.xml)
Spring Bean Configuration File(servlet-context.xml)에 파일 업로드 기능을 제공하는 클래스를 Spring Bean으로 등록
MultipartHttpServletRequest 객체를 사용하여 [multipart/form-data] 형태로 전달된 값 또는 파일 처리
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.5</version>
</dependency>
<beans:bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver" id="multipartResolver">
<!-- maxUploadSize 필드에 최대 업로드 파일의 제한 용량(Byte)을 주입 -->
<beans:property name="maxUploadSize" value="20971520"/>
<!-- defaultEncoding 필드에 전달값에 대한 문자형태(캐릭터셋)을 주입 -->
<beans:property name="defaultEncoding" value="utf-8"/>
</beans:bean>
방법1
- 요청 처리 메소드에 MultipartHttpServletRequest 인터페이스로 매개변수를 선언하면 Front Controller에 의해 MultipartHttpServletRequest 객체를 제공받아 사용 가능
- MultipartHttpServletRequest 객체 : [multipart/form-data] 형식으로 전달된 값 또는 파일을 처리하기 위한 객체
- MultipartHttpServletRequest.getParameter(String name) : [multipart/form-data] 형식으로 전달된 값을 문자열(String 객체)로 반환하는 메소드
String uploaderName=request.getParameter("uploaderName");
- MultipartHttpServletRequest.getFile(String name) : [multipart/form-data] 형식으로 전달된 파일을 MultipartFile 객체로 반환하는 메소드
- MultipartFile 객체 : 사용자로부터 입력되어 전달된 파일정보를 저장하기 위한 객체
MultipartFile uploadFile=request.getFile("uploadFile");
전달받은 파일에 대한 검증 작업
String uploadDirectory=request.getServletContext().getRealPath("/resources/images/upload");
- 전달파일을 서버 디렉토리에 저장하기 위한 File 객체 생성
- File 객체 : 시스템에 존재하는 파일정보를 저장하기 위한 객체
- MultipartFile.getOriginalFilename() : 전달파일의 파일명을 반환하는 메소드
File file=new File(uploadDirectory, uploadFile.getOriginalFilename());
- MultipartFile.transferTo(File file) : MultipartFile 객체에 저장된 파일정보를 File 객체(서버 디렉토리)에 저장된 파일정보로 전달하여 저장하는 메소드 (업로드 처리 메소드)
uploadFile.transferTo(file);
방법2
- 요청 처리 메소드에 매개변수를 작성하여 전달값과 전달파일을 제공받아 사용 가능
public String upload(@RequestParam String uploaderName, @RequestParam MultipartFile uploadFile, Model model)
- 업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 기존 파일 대신 업로드 파일이 저장 : 덮어씌위기(OverWrite)
- 전달파일을 저장하기 위한 서버 디렉토리의 시스템 경로를 반환받아 저장
- WebApplicationContext 객체(Spring Container)에게 ServletContext 객체를 제공받아 사용```
String uploadDirectory=context.getServletContext().getRealPath("/resources/images/upload");
- 사용자로부터 입력되어 전달된 원본 파일명을 반환받아 저장
String originalFilename=uploadFile.getOriginalFilename();
- 서버 디렉토리에 저장하기 위한 파일정보가 저장된 File 객체 생성
File file=new File(uploadDirectory, originalFilename);
- 서버 디렉토리에 저장될 파일명을 저장하기 위한 변수 (초기값으로 사용자로부터 입력되어 전달된 원본 파일명을 저장)
String uploadFilename=originalFilename;
package xyz.itwill10.controller;
@Controller
@RequiredArgsConstructor
public class FileController {
//WebApplicationContext 객체(Spring Container)를 제공받아 필드에 의존성 주입
private final WebApplicationContext context;
@RequestMapping(value = "/upload", method = RequestMethod.GET)
public String upload() {
return "file/upload_form";
}
/*
//요청 처리 메소드에 MultipartHttpServletRequest 인터페이스로 매개변수를 선언하면 Front
//Controller에 의해 MultipartHttpServletRequest 객체를 제공받아 사용 가능
//MultipartHttpServletRequest 객체 : [multipart/form-data] 형식으로 전달된 값 또는 파일을
//처리하기 위한 객체
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(MultipartHttpServletRequest request) throws IOException {
//MultipartHttpServletRequest.getParameter(String name) : [multipart/form-data]
//형식으로 전달된 값을 문자열(String 객체)로 반환하는 메소드
String uploaderName=request.getParameter("uploaderName");
//MultipartHttpServletRequest.getFile(String name) : [multipart/form-data] 형식으로
//전달된 파일을 MultipartFile 객체로 반환하는 메소드
//MultipartFile 객체 : 사용자로부터 입력되어 전달된 파일정보를 저장하기 위한 객체
MultipartFile uploadFile=request.getFile("uploadFile");
//전달받은 파일에 대한 검증 작업
//MultipartFile.isEmpty() : MultipartFile 객체에 파일정보가 없는 경우 [false]를 반환하고
//파일정보가 있는 경우 [true]를 반환하는 메소드
if(uploadFile.isEmpty()) {
return "file/upload_fail";
}
//MultipartFile.getContentType() : MultipartFile 객체에 저장된 파일의 형식(MimeType)를 반환하는 메소드
System.out.println("파일 형식 = "+uploadFile.getContentType());
//MultipartFile.getBytes() : MultipartFile 객체에 저장된 파일정보를 byte 배열로 반환하는 메소드
System.out.println("파일 크기 = "+uploadFile.getBytes().length);
//전달파일을 저장하기 위한 서버 디렉토리의 시스템 경로를 반환받아 저장
String uploadDirectory=request.getServletContext().getRealPath("/resources/images/upload");
System.out.println("uploadDirectory = "+uploadDirectory);
//전달파일을 서버 디렉토리에 저장하기 위한 File 객체 생성
//File 객체 : 시스템에 존재하는 파일정보를 저장하기 위한 객체
//MultipartFile.getOriginalFilename() : 전달파일의 파일명을 반환하는 메소드
File file=new File(uploadDirectory, uploadFile.getOriginalFilename());
//MultipartFile.transferTo(File file) : MultipartFile 객체에 저장된 파일정보를
//File 객체에 저장된 파일정보로 전달하여 저장하는 메소드 - 업로드 처리 메소드
uploadFile.transferTo(file);
request.setAttribute("uploaderName", uploaderName);
request.setAttribute("uploadFilename", uploadFile.getOriginalFilename());
return "file/upload_ok";
}
*/
//요청 처리 메소드에 매개변수를 작성하여 전달값과 전달파일을 제공받아 사용 가능
// => 업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 기존 파일 대신 업로드
//파일이 저장 - 덮어씌위기(OverWrite)
// => commons-fileupload 라이브러리에는 업로드 파일을 변경하는 기능의 클래스 미존재
// => 업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 업로드 파일명을 변경하는 명령 작성 필요
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public String upload(@RequestParam String uploaderName
, @RequestParam MultipartFile uploadFile, Model model) throws IOException {
if(uploadFile.isEmpty()) {
return "file/upload_fail";
}
//전달파일을 저장하기 위한 서버 디렉토리의 시스템 경로를 반환받아 저장
// => WebApplicationContext 객체(Spring Container)에게 ServletContext 객체를 제공받아 사용
String uploadDirectory=context.getServletContext().getRealPath("/resources/images/upload");
//사용자로부터 입력되어 전달된 원본 파일명을 반환받아 저장
String originalFilename=uploadFile.getOriginalFilename();
//서버 디렉토리에 저장하기 위한 파일정보가 저장된 File 객체 생성
File file=new File(uploadDirectory, originalFilename);
//서버 디렉토리에 저장될 파일명을 저장하기 위한 변수
// => 초기값으로 사용자로부터 입력되어 전달된 원본 파일명을 저장
String uploadFilename=originalFilename;
//업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 서버 디렉토리에
//저장될 파일명을 구분하기 위한 식별자를 저장하기 위한 변수
int i=0;
//File.exists() : File 객체에 저장된 파일이 시스템이 존재하지 않을 경우 [false]를
//반환하고 존재할 경우 [true]를 반환하는 메소드
while(file.exists()) {//업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 반복 처리
i++;
//파일명과 확장자를 구분하기 위한 문자열(.)를 사용하여 위치값(Index)을 반환받아 저장
int index=originalFilename.lastIndexOf(".");
//원본 파일명을 이용하여 업로드 파일명 생성
uploadFilename=originalFilename.substring(0, index)+"_"+i+originalFilename.substring(index);
//서버 디렉토리에 저장될 파일명을 저장하기 위한 변수
file=new File(uploadDirectory, uploadFilename);
}
//파일의 이름을 변경하여 업로드 처리
uploadFile.transferTo(file);
model.addAttribute("uploaderName", uploaderName);
model.addAttribute("originalFilename", originalFilename);
model.addAttribute("uploadFilename", uploadFilename);
return "file/upload_ok";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
<h1>파일 업로드</h1>
<hr>
<%-- 파일 업로드 : 클라이언트로부터 파일을 입력받아 서버 디렉토리에 저장하는 기능 --%>
<%-- => 파일을 입력받아 전달하기 위한 form 태그를 사용하며 요청방식(method 속성)은
반드시 [post]로 설정하고 전달형태(enctype 속성)은 [mulitpart/form-data]로 설정 --%>
<form action="upload" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>업로더 이름</td>
<td><input type="text" name="uploaderName"></td>
</tr>
<tr>
<td>업로드 파일</td>
<td><input type="file" name="uploadFile"></td>
</tr>
<tr>
<td colspan="2"><button type="submit">업로드</button></td>
</tr>
</table>
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
<h1>파일 업로드 성공</h1>
<hr>
<%--
<p>업로더 이름 = ${uploaderName }</p>
<p>업로드 파일명 = ${uploadFilename }</p>
--%>
<p>업로더 이름 = ${uploaderName }</p>
<p>원본 파일명 = ${originalFilename }</p>
<p>업로드 파일명 = ${uploadFilename }</p>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
<h1>파일 업로드 실패</h1>
<hr>
</body>
</html>
create table fileboard(num number primary key, writer varchar2(20), subject varchar2(100),
origin varchar2(100), upload varchar2(100));
create sequence fileboard_seq;
package xyz.itwill10.dto;
/*
이름 널? 유형
------- -------- -------------
NUM NOT NULL NUMBER - 글번호
WRITER VARCHAR2(20) - 작성자
SUBJECT VARCHAR2(100) - 제목
ORIGIN VARCHAR2(100) - 원본 파일명
UPLOAD VARCHAR2(100) - 업로드 파일명(서버 디렉토리에 저장되는 파일명)
*/
//DTO 클래스 >> 전달값을 제공받아 사용하기 위한 Command 객체의 클래스
@Data
public class FileBoard {
private int num;
private String writer;
private String subject;
private String origin;
private String upload;
private MultipartFile file;//전달파일을 저장하기 위한 필드
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.itwill10.mapper.FileBoardMapper">
<insert id="insertFileBoard">
<selectKey resultType="int" keyProperty="num" order="BEFORE">
select fileboard_seq.nextval from dual
</selectKey>
insert into values fileboard(#{num},#{writer},#{subject},#{origin},#{upload})
</insert>
<delete id="deleteFileBoard">
delete from fileboard where num=#{num}
</delete>
<select id="selectFileBoard" resultType="FileBoard">
select * from fileboard where num=#{num}
</select>
<select id="selectFileBoardList" resultType="FileBoard">
select * from fileboard order by num desc
</select>
</mapper>
package xyz.itwill10.mapper;
import java.util.List;
import xyz.itwill10.dto.FileBoard;
public interface FileBoardMapper {
int insertFileBoard(FileBoard fileBoard);
int deleteFileBoard(int num);
FileBoard selectFileBoard(int num);
List<FileBoard> selectFileBoardList();
}
package xyz.itwill10.dao;
import java.util.List;
import xyz.itwill10.dto.FileBoard;
public interface FileBoardDAO {
int insertFileBoard(FileBoard fileBoard);
int deleteFileBoard(int num);
FileBoard selectFileBoard(int num);
List<FileBoard> selectFileBoardList();
}
package xyz.itwill10.dao;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.springframework.stereotype.Repository;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dto.FileBoard;
import xyz.itwill10.mapper.FileBoardMapper;
@Repository
@RequiredArgsConstructor
public class FileBoardDAOImpl implements FileBoardDAO {
private final SqlSession sqlSession;
@Override
public int insertFileBoard(FileBoard fileBoard) {
return sqlSession.getMapper(FileBoardMapper.class).insertFileBoard(fileBoard);
}
@Override
public int deleteFileBoard(int num) {
return sqlSession.getMapper(FileBoardMapper.class).deleteFileBoard(num);
}
@Override
public FileBoard selectFileBoard(int num) {
return sqlSession.getMapper(FileBoardMapper.class).selectFileBoard(num);
}
@Override
public List<FileBoard> selectFileBoardList() {
return sqlSession.getMapper(FileBoardMapper.class).selectFileBoardList();
}
}
package xyz.itwill10.service;
import java.util.List;
import xyz.itwill10.dto.FileBoard;
public interface FileBoardService {
void addFileBoard(FileBoard fileBoard);
void removeFileBoard(int num);
FileBoard getFileBoard(int num);
List<FileBoard> getFileBoardList();
}
package xyz.itwill10.service;
import java.util.List;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import xyz.itwill10.dao.FileBoardDAO;
import xyz.itwill10.dto.FileBoard;
@Service
@RequiredArgsConstructor
public class FileBoardServiceImpl implements FileBoardService {
private final FileBoardDAO fileBoardDAO;
@Override
public void addFileBoard(FileBoard fileBoard) {
fileBoardDAO.insertFileBoard(fileBoard);
}
@Override
public void removeFileBoard(int num) {
fileBoardDAO.deleteFileBoard(num);
}
@Override
public FileBoard getFileBoard(int num) {
return fileBoardDAO.selectFileBoard(num);
}
@Override
public List<FileBoard> getFileBoardList() {
return fileBoardDAO.selectFileBoardList();
}
}
<!-- BeanNameViewResolver 클래스를 Spring Bean으로 등록 -->
<beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<beans:property name="order" value="1"/>
</beans:bean>
BeanNameViewResolver : 요청 처리 메소드에서 반환되는 문자열(ViewName)을 제공받아 같은 이름(beanName)의 객체(Spring Bean)의 실행 메소드를 호출하여 클라이언트에게 응답
UrlBasedViewResolver 객체 : 클라이언트 요청에 의해 호출되는 요청 처리 메소드의 반환값(ViewName)을 제공받아 Spring Framework가 제공하는 ViewResolver 객체가 아닌 외부의 뷰프로그램을 이용하여 응답 처리하는 객체
InternalResourceViewResolver 객체 : 클라이언트 요청에 의해 호출되는 요청 처리 메소드의 반환값(ViewName)을 제공받아 응답 가능한 JSP 문서로 변환하여 반환하는 객체
전달파일이 저장될 서버 디렉토리의 시스템 경로를 반환받아 저장
String uploadDir=context.getServletContext().getRealPath("/WEB-INF/upload");
서버 디렉토리에 저장된 업로드 파일명을 생성하여 저장
String upload=System.currentTimeMillis()+"";
package xyz.itwill10.controller;
@Controller
@RequiredArgsConstructor
public class FileController {
//WebApplicationContext 객체(Spring Container)를 제공받아 필드에 의존성 주입
private final WebApplicationContext context;
private final FileBoardService fileBoardService;
@RequestMapping(value = "/fileboard/write", method = RequestMethod.GET)
public String fileBoardWrite() {
return "file/board_write";
}
//매개변수를 작성하여 모든 전달값과 전달파일을 Command 객체로 제공받아 사용 가능
@RequestMapping(value = "/fileboard/write", method = RequestMethod.POST)
public String fileBoardWrite(@ModelAttribute FileBoard fileBoard) throws IllegalStateException, IOException {
if(fileBoard.getFile().isEmpty()) {
return "file/board_write";
}
//전달파일이 저장될 서버 디렉토리의 시스템 경로를 반환받아 저장
// => 다운로드 프로그램에서만 파일에 접근 가능하도록 /WEB-INF 폴더에 업로드 폴더 작성
String uploadDir=context.getServletContext().getRealPath("/WEB-INF/upload");
//사용자로부터 입력받아 전달된 원본파일의 이름을 반환받아 저장
String origin=fileBoard.getFile().getOriginalFilename();
//서버 디렉토리에 저장된 업로드 파일명을 생성하여 저장
// => 업로드 파일명은 서버 디렉토리에 존재하는 파일명과 중복되지 않도록 고유값 사용
// => 업로드 파일명은 시스템의 현재 날짜와 시간에 대한 정수값(TimeStamp)를 사용하여 작성
String upload=System.currentTimeMillis()+"";
//Command 객체(FileBoard 객체)의 필드값 변경
fileBoard.setOrigin(origin);
fileBoard.setUpload(upload);
//파일 업로드 처리
fileBoard.getFile().transferTo(new File(uploadDir, upload));
//FILEBOARD 테이블에 행 삽입
fileBoardService.addFileBoard(fileBoard);
return "redirect:/fileboard/list";
}
@RequestMapping("/fileboard/list")
public String fileBoardList(Model model) {
model.addAttribute("fileBoardList", fileBoardService.getFileBoardList());
return "file/board_list";
}
//URL 주소로 전달된 값을 @PathVariable 어노테이션을 사용하여 매개변수로 제공받아 사용
@RequestMapping("/fileboard/delete/{num}")
public String fileBoardDelete(@PathVariable int num) {
FileBoard fileBoard=fileBoardService.getFileBoard(num);
String uploadDir=context.getServletContext().getRealPath("/WEB-INF/upload");
//서버 디렉토리에 저장된 업로드 파일을 삭제 처리
new File(uploadDir, fileBoard.getUpload()).delete();
fileBoardService.removeFileBoard(num);
return "redirect:/fileboard/list";
}
@RequestMapping("/fileboard/download/{num}")
public String fileBoardDownload(@PathVariable int num, Model model) {
FileBoard fileBoard=fileBoardService.getFileBoard(num);
//Model 객체를 이용하여 실행될 프로그램(Spring Bean)에서 사용하기 위한 객체를 속성값으로 저장하여 제공
model.addAttribute("uploadDir", context.getServletContext().getRealPath("/WEB-INF/upload"));
model.addAttribute("uploadFilename",fileBoard.getUpload());
model.addAttribute("originalFilename",fileBoard.getOrigin());
//실행될 프로그램(Spring Bean)의 식별자(beanName)를 반환
// => 실행될 프로그램에 대한 클래스를 작성하여 Spring Bean Configuration File
//(servlet-context.xml)에 Spring Bean으로 등록
return "fileDownload";
}
}
public FileDownload() {setContentType("application/download; utf-8");}
package xyz.itwill10.util;
public class FileDownload extends AbstractView {
//클라이언트에게 응답될 파일형식(MimeType)에 대한 변경 - 파일 다운로드 기능
public FileDownload() {
//AbstractView.setContentType(String mimeType) : 응답 파일 형식을 변경하는 메소드
setContentType("application/download; utf-8");
}
//BeanNameViewResolver 객체에 의해 자동 호출되는 메소드
// => Map 자료형의 매개변수에는 요청 처리 메소드에서 제공된 속성값이 엔트리로 저장된 Map 객체 제공
@Override
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
//요청 처리 메소드에서 제공된 속성값(파일 관련 정보)을 객체로 반환받아 저장
String uploadDir=(String)model.get("uploadDir");
String uploadFilename=(String)model.get("uploadFilename");
String originalFilename=(String)model.get("originalFilename");
//서버 디렉토리에 저장된 다운로드 파일에 대한 File 객체 생성
File downloadFile=new File(uploadDir, uploadFilename);
//클라이언트에게 파일을 전달하기 위해 리스폰즈 메세지의 머릿부 변경
response.setContentType(getContentType());
response.setContentLengthLong((int)downloadFile.length());
//다운로드 처리되어 클라이언트에 저장될 파일명을 리스폰즈 메세지의 머릿부에 저장하여 전달
// => 파일명에 대한 한글 문제로 인해 부호화 처리하여 전달
originalFilename=URLEncoder.encode(originalFilename, "utf-8");
response.setHeader("Content-Disposition","attachement;filename=\""+originalFilename+"\";");
//리스폰즈 메세지 몸체부에 파일을 전달하여 저장하기 위한 출력스트림을 반환받아 저장
OutputStream out=response.getOutputStream();
//서버 디렉토리에 저장된 다운로드 파일을 읽기 위한 입력스트림을 생성하여 저장
InputStream in=new FileInputStream(downloadFile);
//FileCopyUtils.copy(InputStream in, OutputStream out) : 입력스트림으로 원시데이타를
//반복적으로 읽어 출력스트림으로 전달하는 메소드 - 파일 복사
FileCopyUtils.copy(in, out);
in.close();
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
</head>
<body>
<h1>자료실(입력페이지)</h1>
<hr>
<form method="post" enctype="multipart/form-data">
<table>
<tr>
<td>작성자</td>
<td><input type="text" name="writer"></td>
</tr>
<tr>
<td>제목</td>
<td><input type="text" name="subject"></td>
</tr>
<tr>
<td>파일</td>
<td><input type="file" name="file"></td>
</tr>
<tr>
<td colspan="2"><button type="submit">파일전송</button></td>
</tr>
</table>
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SPRING</title>
<style type="text/css">
table {
border: 1px solid black;
border-collapse: collapse;
}
th, td {
border: 1px solid black;
padding: 2px;
}
</style>
</head>
<body>
<h1>자료실(출력페이지)</h1>
<hr>
<table>
<tr>
<th width="50">번호</th>
<th width="100">작성자</th>
<th width="300">제목</th>
<th width="350">파일명</th>
<th width="100">다운로드</th>
<th width="100">삭제</th>
</tr>
<c:forEach var="fileBoard" items="${fileBoardList }">
<tr>
<td align="center">${fileBoard.num }</td>
<td align="center">${fileBoard.writer }</td>
<td>${fileBoard.subject }</td>
<td>${fileBoard.origin }</td>
<td align="center">
<button type="button" onclick="fileDownload(${fileBoard.num });">다운로드</button>
</td>
<td align="center">
<button type="button" onclick="fileDelete(${fileBoard.num });">삭제</button>
</td>
</tr>
</c:forEach>
</table>
<p>
<button type="button" onclick="location.href='${pageContext.request.contextPath}/fileboard/write';">업로드</button>
</p>
<script type="text/javascript">
function fileDownload(num) {
//URL 주소를 이용하여 자료실 번호 전달
location.href="${pageContext.request.contextPath}/fileboard/download/"+num;
}
function fileDelete(num) {
if(confirm("자료를 정말로 삭제 하시겠습니까?")) {
location.href="${pageContext.request.contextPath}/fileboard/delete/"+num;
}
}
</script>
</body>
</html>