framework/spring mvc 웹사이트제작법

[springMVC웹] 15. 파일 업로드 프로그램 (요청 처리 메소드에서 파일 업로드 처리)

jeri 2024. 8. 5. 20:16
반응형

🌈 파일 업로드 처리를 위한 라이브러리 빌드

01. @Controller

🖤[Controller] FileController.java - 1
package xyz.itwill10.controller;

import java.io.File;
import java.io.IOException;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;

import lombok.RequiredArgsConstructor;

//🌈 파일 업로드 처리를 위한 환경설정 방법
//step1.
//commons-Fileupload 라이브러리를 프로젝트에 빌드 처리 - 메이븐 : pom.xml
//=> [선택적 파일 업로드] : Apache 그룹에서 배포한 commons-fileupload 라이브러리의 클래스 사용
//=> [무조건적 파일 업로드] : Oreilly 그룹에서 배포한 cos 라이브러리의 클래스 사용
//=> 아파치에서 제공해주는 commons-Fileupload는 파일이 전달되면 모두 다 업로드 처리하는 것이 아니라, 원하는 것만 업로드할 수 있음
//step2.
//Spring Bean Configuration File(servlet-context.xml)에
//파일 업로드 기능을 제공하는 클래스를 Spring Bean으로 등록
//step3.
//MultipartHttpServletRequest 객체를 사용하여
//[multipart/form-data] 형태로 전달된 값 또는 파일 처리

@Controller
@RequiredArgsConstructor
public class FileController {
  • 💙필드
	//WebApplicationContext 객체(Spring Container)를 제공받아 필드에 의존성 주입
  	// => 웹과 관련된 객체들이 다 저장되어있음
  	// => 즉 내부적으로 requset 객체, servletcontext 객체 모두 가지고 있으니 내부 메소드에서 사용하자!!
	private final WebApplicationContext context;
  • 💙요청처리 메소드 [GET] : /upload 요청
	@RequestMapping(value = "/upload", method = RequestMethod.GET)
	public String upload() {
		return "file/upload_form";
	}
  • 💙요청처리 메소드 [POST] : /upload 요청
	//[방법1]	
	//문제점 : 필요한 값을 반환받아 쓰는 것은 매우 불편, 매개변수로 제공받아 사용하는 것이 좋음, 보완하자
	//요청 처리 메소드에 MultipartHttpServletRequest 인터페이스로 매개변수를 선언하면 Front
	//Controller에 의해 MultipartHttpServletRequest 객체를 제공받아 사용 가능
	//MultipartHttpServletRequest 객체 : [multipart/form-data] 형식으로 전달된 값 또는 파일을
	//처리하기 위한 객체
	@RequestMapping(value = "/upload", method = RequestMethod.POST)
	public String upload(MultipartHttpServletRequest request) throws IOException {
  	//1.
		//MultipartHttpServletRequest.getParameter(String name) : [multipart/form-data]형식으로 전달된 값을 문자열(String 객체)로 반환하는 메소드
		String uploaderName=request.getParameter("uploaderName");
		//2.
		//MultipartHttpServletRequest.getFile(String name) : [multipart/form-data] 형식으로 전달된 파일을 MultipartFile 객체로 반환하는 메소드
		//MultipartFile 객체 : 사용자로부터 입력되어 전달된 파일정보를 저장하기 위한 객체
		MultipartFile uploadFile=request.getFile("uploadFile");
		//3.
		//전달받은 파일에 대한 검증 작업
    	//=> 자바스크립트로는 파일이 있다 없다의 검증은 가능하지만 그 외의 검증작업 불가능하므로 여기서 파일 검증 하는 것을 권장       
    	//3-검증1.
		//MultipartFile.isEmpty() : MultipartFile 객체에 파일정보가 없는 경우 [false]를 반환하고 파일정보가 있는 경우 [true]를 반환하는 메소드
		if(uploadFile.isEmpty()) {
			return "file/upload_fail";
		}
		//3-검증2. 여기서는 출력만 했지만, 실제로 만들 때는 검증 작업 해주기!
		//MultipartFile.getContentType() : MultipartFile 객체에 저장된 파일의 형식(MimeType)를 반환하는 메소드
		System.out.println("파일 형식 = "+uploadFile.getContentType());        
    	//3-검증3. 여기서는 출력만 했지만, 실제로 만들 때는 검증 작업 해주기!
		//MultipartFile.getBytes() : MultipartFile 객체에 저장된 파일정보를 byte 배열로 반환하는 메소드
		System.out.println("파일 크기 = "+uploadFile.getBytes().length);
		//4.
		//전달파일을 저장하기 위한 서버 디렉토리의 시스템 경로를 반환받아 저장
		String uploadDirectory=request.getServletContext().getRealPath("/resources/images/upload");
		System.out.println("uploadDirectory = "+uploadDirectory);
		//5.
		//전달파일을 서버 디렉토리에 저장하기 위한 File 객체 생성
		//File 객체 : 시스템에 존재하는 파일정보를 저장하기 위한 객체
		//MultipartFile.getOriginalFilename() : 전달파일의 파일명을 반환하는 메소드
		File file=new File(uploadDirectory, uploadFile.getOriginalFilename());
		//6.
		//MultipartFile.transferTo(File file) : MultipartFile 객체에 저장된 파일정보를 File 객체에 저장된 파일정보로 전달하여 저장하는 메소드
		uploadFile.transferTo(file); //업로드 처리 메소드 호출!
		//7.
		request.setAttribute("uploaderName", uploaderName);
		request.setAttribute("uploadFilename", uploadFile.getOriginalFilename());
		//8.
		return "file/upload_ok";
	}

	//[방법2]
	//해결법 : 매개변수로 제공받아 사용할 수 있으므로 request 객체에게 달라고 하지 않아도 됨!    
	//요청 처리 메소드에 "매개변수를 작성"하여 "전달값"과 "전달파일"을 "제공"받아 사용 가능
	//문제점) 업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 기존 파일 대신 업로드
	//파일이 저장 - 덮어씌위기(OverWrite)
	// => commons-fileupload 라이브러리에는 업로드 파일의 이름을 변경하는 기능의 클래스 미존재
	// => 업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 업로드 파일명을 변경하는 명령 작성 필요
	@RequestMapping(value = "/upload", method = RequestMethod.POST)
	public String upload(@RequestParam String uploaderName, @RequestParam MultipartFile uploadFile, Model model) throws IOException {
		//1.
		if(uploadFile.isEmpty()) {
			return "file/upload_fail";
		}
		//2.
		//전달파일을 저장하기 위한 서버 디렉토리의 시스템 경로를 반환받아 저장
		// => WebApplicationContext 객체(Spring Container)에게 ServletContext 객체를 제공받아 사용
		String uploadDirectory=context.getServletContext().getRealPath("/resources/images/upload");
		//3.
		//사용자로부터 입력되어 전달된 원본 파일명을 반환받아 저장
		String originalFilename=uploadFile.getOriginalFilename();
		//4.
		//서버 디렉토리에 저장하기 위한 파일정보가 저장된 File 객체 생성
		File file=new File(uploadDirectory, originalFilename);
		//5.
		//업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 업로드 파일명을 변경할 수 있도록 작성
		//5-1.
		//서버 디렉토리에 저장될 파일명을 저장하기 위한 변수
		// => 초기값으로 사용자로부터 입력되어 전달된 원본 파일명을 저장
		String uploadFilename=originalFilename;
		//5-2.
		//업로드 파일과 같은 이름의 파일이 서버 디렉토리에 존재할 경우 서버 디렉토리에
		//저장될 파일명을 구분하기 위한 식별자를 저장하기 위한 변수
		int i=0;
		//5-3.
		//File.exists() : File 객체에 저장된 파일이 시스템이 존재하지 않을 경우 [false]를
		//반환하고 존재할 경우 [true]를 반환하는 메소드
		while(file.exists()) {//업로드 파일과 같은 이름의 파일이 서버 디렉토리에 "존재"할 경우 반복 처리
        
			i++; //존재하면 1씩 증가 [ex)koala.jpg -> koala1.jpg]

			//파일명과 확장자를 구분하기 위한 문자열(.)를 사용하여 위치값(Index)을 반환받아 저장
			int index=originalFilename.lastIndexOf(".");
			//원본 파일명을 이용하여 업로드 파일명 생성
			uploadFilename=originalFilename.substring(0, index)+"_"+i+originalFilename.substring(index);
			//서버 디렉토리에 저장될 파일명을 저장하기 위한 변수
			file=new File(uploadDirectory, uploadFilename);
		}

		//5-4.
		//파일의 이름을 변경하여 업로드 처리
		uploadFile.transferTo(file);

		//6.
		model.addAttribute("uploaderName", uploaderName);
		model.addAttribute("originalFilename", originalFilename);
		model.addAttribute("uploadFilename", uploadFilename);

		//7.
		return "file/upload_ok";
	}

}

02. VIEW

💚[JSP]upload_form.jsp
<%@ 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]로 설정 -->
	<!-- => 인코딩하지 않은 원시데이타(multipart/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>
💚[JSP] upload_fail.jsp
<%@ 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>
💚[JSP] upload_ok.jsp
<%@ 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>

03. 테이블, DTO

🖤[테이블, DTO] FileBoard.java

FileBoard : 실제 테이블에는 파일 자체를 저장하는 것이 아닌 파일명을 저장하는 것!

  • 그러나 파일을 저장할 수 있는 자료형이 있긴 함 : CLOB(텍스트 파일) ,BLOB(모든 파일)
  • 그러나 파일을 저장하는 컬럼을 사용하지는 않음
  • 왜? 데이타 저장하는 용량을 많이 차지하므로 속도가 매우 느려짐
package xyz.itwill10.dto;

import org.springframework.web.multipart.MultipartFile;

import lombok.Data;

//create table fileboard(num number primary key, writer varchar2(20), subject varchar2(100)
//	,origin varchar2(100), upload varchar2(100));
//create sequence fileboard_seq;

/*
이름      널?       유형
------- -------- -------------
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 update;
    
  //전달파일을 저장하기 위한 필드 - 만드는 것을 권장
  //실제 테이블에는 해당 컬럼은 없지만 전달값을 저장하기 위해 필드를 생성함 - Command 객체의 역할
	private MultipartFile file;
}

 

 

04. Mapper바인딩

💛[Mapper] FileBoardMapper.xml
<?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 fileboard values(#{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>
💛[Mapper] FileBoardMapper.java
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();
}

05. @Repository

🖤[DAO] FileBoardDAO.java
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();
}
🖤[DAO] FileBoardDAOImpl.java
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();
	}

}

06. @Service

🖤[Service] (부모) FileBoardService.java
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();
}
🖤[Service] (자식) FileBoardServiceImpl.java
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();
	}

}

07. @Controller

🖤[Controller] FileController.java - 2
package xyz.itwill10.controller;

import java.io.File;
import java.io.IOException;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;

import lombok.RequiredArgsConstructor;
import xyz.itwill10.dto.FileBoard;
import xyz.itwill10.service.FileBoardService;

@Controller
@RequiredArgsConstructor
public class FileController {

	//WebApplicationContext 객체(Spring Container)를 제공받아 필드에 의존성 주입
	private final WebApplicationContext context;
	private final FileBoardService fileBoardService;
  • 💙[GET] : /fileboard/write 요청
	@RequestMapping(value = "/fileboard/write", method = RequestMethod.GET)
	public String fileBoardWrite() {
		return "/file/board_write";
	}
  • 💙[POST] : /fileboard/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 폴더에 업로드 폴더 작성
		// => 즉, 클라이언트가 아예 접근할 수 없음. 오직 다운로드 프로그램에서만 접근 가능!
		// => vs [/resources/upload : 클라가 접근 가능한 폴더]
		// =>    [/WEB-INF/upload : 클라가 접근 불가능한 폴더]
		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";
	}
  • 💙/fileboard/list 요청
	@RequestMapping("/fileboard/list")
	public String fileBoardList(Model model) {
		model.addAttribute("fileBoardList", fileBoardService.getFileBoardList());
		return "file/board_list";
	}
  • 💙/fileboard/delete/{num} 요청
	//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";
	}
  • 💙/fileboard/download/{num} 요청 - 다운로드 프로그램(클래스) 필요!!
	//다운로드(Download) : 서버 디렉토리에 존재하는 파일을 클라이언트에 전달하여 저장하는 기능
	//요청 처리 메소드에 의해 반환되는 문자열(ViewName)으로 다운로드 프로그램을 실행하여 서버 디렉토리에 저장된 파일을 클라이언트에게 전달하여 응답 처리
   
	// => BeanNameViewResolver[1st] 객체를 사용하여 반환하는 문자열로 특정 프로그램 실행
	// => Spring Bean Configuration File(servlet-context.xml)에 BeanNameViewResolver 클래스를 Spring Bean으로 등록
    
	//현재 사용중인 ViewResolver 객체는 요청 처리 메소드에서 반환되는 문자열을 이용해 JSP 문서로 응답되도록 처리
	// => UrlBasedViewResolver(TilesView)[2nd], InternalResourceViewResolver[3rd]
    
	@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";
	}

}

 

08. VIEW

💚board_write.jsp (입력페이지 - 파일 업로드 기능구현)
<%@ 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>
		<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>
💚board_list.jsp ( 출력페이지 - 파일 다운로드 기능 구현)
<%@ 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>

 

반응형