Dev/Struts

Struts2 - 파일업로드/다운로드/보기 기능 구현

창문닦이 2019. 3. 26. 15:11

일반적으로 프레임워크는 파일을 업로드시키는 고유 방법을 내장하고 있다. Struts2를 활용한 파일업로드,다운로드,뷰 기능을 구현해보자.

1. DTO 생성

package com.fileTest;

import java.io.File;

public class FileTestDTO {

private File upload;//jsp페이지의 input태그의 type=file, name=upload인 데이터

//위에서 정의한 upload에 FileName을 붙이면 Struts2가 자동으로 파일 이름을 넣어준다.

private String uploadFileName; //struts2방식 File클래스 이름뒤에 FileName을 붙임

private String mode;

public File getUpload() {

return upload;

}

public void setUpload(File upload) {

this.upload = upload;

}

public String getUploadFileName() {

return uploadFileName;

}

public void setUploadFileName(String uploadFileName) {

this.uploadFileName = uploadFileName;

}

public String getMode() {

return mode;

}

public void setMode(String mode) {

this.mode = mode;

}

}

2. Action클래스 생성 - created()메소드 업로드 기능

package com.fileTest;

import java.io.File;

import java.io.InputStream;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpSession;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

import com.opensymphony.xwork2.ModelDriven;

import com.opensymphony.xwork2.Preparable;

import com.util.FileManager;

public class FileTestAction extends ActionSupport

implements Preparable,ModelDriven<FileTestDTO>{

private FileTestDTO dto;

//request.setAttribute("dto",dto);를 대신하는 것이 getDTO();

public FileTestDTO getDto() {

return dto;

}

private static final long serialVersionUID = 1L;

@Override

public FileTestDTO getModel() {

return dto;//객체에 데이터담음

}

@Override

public void prepare() throws Exception {

dto = new FileTestDTO();//객체생성

}

//파일업로드

public String created() throws Exception{

//dto.getMode()==null||dto.getMode().equals("") 순서 바뀌면 오류남

if(dto==null||dto.getMode()==null||dto.getMode().equals("")){

return INPUT;

}

HttpServletRequest request = ServletActionContext.getRequest();

HttpSession session = request.getSession();

String root = session.getServletContext().getRealPath("/");

String savePath = root + File.separator + "pds" + File.separator + "data";

saveFileName = FileManager.doFileUpload(dto.getUpload(), dto.getUploadFileName(), savePath);

originalFileName = dto.getUploadFileName();

return SUCCESS;

}

//실무에서 Action에 변수생성하고 getter,setter 작성시 맨 밑에 작성하기도 함!

private InputStream inputStream;//파일보기. 눌렀을때 실행이 되도록

private String saveFileName; //서버에 저장된 파일명

private String originalFileName;//사용자가 등록한 파일명

public InputStream getInputStream() {

return inputStream;

}

public void setInputStream(InputStream inputStream) {

this.inputStream = inputStream;

}

public String getSaveFileName() {

return saveFileName;

}

public void setSaveFileName(String saveFileName) {

this.saveFileName = saveFileName;

}

public String getOriginalFileName() {

return originalFileName;

}

public void setOriginalFileName(String originalFileName) {

this.originalFileName = originalFileName;

}

}

3. FileManager 클래스 - 업로드 기능

package com.util;

import java.io.BufferedInputStream;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.OutputStream;

import java.util.Calendar;

import javax.servlet.http.HttpServletResponse;

public class FileManager {

//업로드

//path 파일을 저장한 경로

//return : 서버에 저장할 새로운 파일 이름

public static String doFileUpload(File file,String originalFileName, String path) throws Exception{

String newFileName = null;

if(file==null){

return null;

}

if(originalFileName.equals("")){

return null;

}

//확장자 분리

String fileExt = originalFileName.substring(originalFileName.lastIndexOf("."));

if(fileExt==null ||fileExt.equals("")){

return null;

}

//서버에 저장할 파일명 생성

newFileName = String.format("%1$tY%1$tm%1$td%1$tH%1$tM%1$tS", Calendar.getInstance());

//Y m d H M S 1$를 나눠씀 년월일시분초로 파일이름을 생성

//시분초가 같을 수 있기 때문에

newFileName += System.nanoTime(); //10의 -9승 절대 중복되는 파일을 생성할 수 없게 만듬

newFileName += fileExt;

File f = new File(path);

if(!f.exists()){

f.mkdirs();

}

String fullFilePath = path + File.separator + newFileName;

// 파일업로드 작업

FileInputStream fis = new FileInputStream(file);

FileOutputStream fos = new FileOutputStream(fullFilePath);

int byteRead = 0;

byte[] buffer = new byte[1024];

while((byteRead=fis.read(buffer,0,1024))!=-1){

fos.write(buffer,0,byteRead);//fileData를 올려라

}

fos.close();

fis.close();

return newFileName;

}

}

4. Action클래스의 다운로드 메소드 생성

//파일다운로드

public String download() throws Exception{

HttpServletRequest request = ServletActionContext.getRequest();

HttpServletResponse response = ServletActionContext.getResponse();

HttpSession session = request.getSession();

String root = session.getServletContext().getRealPath("/");

String savePath = root + File.separator + "pds" + File.separator + "data";

FileManager.doFileDownload(saveFileName, originalFileName, savePath, response);

return null;

}

5. FileManager 클래스 - 다운로드기능

//파일 다운로드

//saveFileName : 서버의 저장된 파일이름

//originalFileName : 클라이언트가 업로드한 파일명

//path : 서버에 저장된 경로

public static boolean doFileDownload(String saveFileName, String originalFileName, String path, HttpServletResponse response){

String fullFilePath = path + File.separator + saveFileName;

try {

if(originalFileName==null || originalFileName.equals("")){

originalFileName = saveFileName;

}

originalFileName = new String(originalFileName.getBytes("euc-kr"), "8859_1"); //ISO 8859-1을 생략하면 8859_1

} catch (Exception e) {

System.out.println(e.toString());

}

try {

File f = new File(fullFilePath);

if(f.exists()){

byte readByte[] = new byte[4096];

response.setContentType("application/octet-stream");

response.setHeader("content-disposition", "attachment;fileName="+originalFileName);

BufferedInputStream fis = new BufferedInputStream(new FileInputStream(f));

OutputStream os = response.getOutputStream();

int read;

while((read=fis.read(readByte,0,4096))!=-1){

os.write(readByte, 0 ,read);

}

os.flush();

os.close();

fis.close();

return true;

}

} catch (Exception e) {

System.out.println(e.toString());

}

return false;

}

6. 파일업로드 페이지 - write.jsp

<%@ page contentType="text/html; charset=UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%

request.setCharacterEncoding("UTF-8");

String cp = request.getContextPath();

%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>업로드</title>

</head>

<body>

<form action="<%=cp%>/fileTest/created.action" method="post"

enctype="multipart/form-data">

여기서 인풋태그의 이름이 DTO의 변수명과 동일해야함!!!

파일 : <input type="file" name="upload"/><br/>

<input type="hidden" name="mode" value="save">

<input type="submit" value="파일업로드"/>

</form>

</body>

</html>

7. 파일 다운로드/조회 페이지 - view.jsp

<%@page import="java.net.URLDecoder"%>

<%@ page contentType="text/html; charset=UTF-8"%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%

request.setCharacterEncoding("UTF-8");

String cp = request.getContextPath();

%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Insert title here</title>

</head>

<body>

리스트겸 파일 다운로드<br>

<a href="<%=cp%>/fileTest/download.action?

saveFileName=${saveFileName}&originalFileName=${originalFileName}">

${dto.uploadFileName}

</a>

<br>

<br>

파일보기<br>

<a href="<%=cp%>/fileTest/downView.action?

saveFileName=${saveFileName}&originalFileName=${originalFileName}">

${dto.uploadFileName}

</a>

</body>

</html>

8. Action클래스의 downView 메소드 생성

파일을 다운로드받지 않고 조회하는 기능

//파일보기

public String downView() throws Exception{

HttpServletRequest request = ServletActionContext.getRequest();

HttpSession session = request.getSession();

String root = session.getServletContext().getRealPath("/");

String savePath = root + File.separator + "pds" + File.separator + "data";

originalFileName = new String(originalFileName.getBytes("euc-kr"),"ISO-8859-1");

String fullFileName = savePath + File.separator + saveFileName;

inputStream = new FileInputStream(fullFileName);

return SUCCESS;

}

9. struts.xml 등록

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

 <!-- Configuration for the default package. -->

  <package name="default" extends="struts-default" namespace="" >       

      <global-results>

          <result name="error">/exception/error.jsp</result>

      </global-results>

 </package>

 <include file="struts-test.xml"/>

 <include file="struts-board.xml"/>

 <include file="struts-inter.xml"/>

 <include file="struts-chain.xml"/>

 <include file="struts-fileTest.xml"/>

</struts>

10. struts-fileTest.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"

"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

<package name="fileTest" extends="struts-default" namespace="/fileTest" >       

<action name="created" method="created" class="com.fileTest.FileTestAction">

<result name="input">/fileTest/write.jsp</result>

<result name="success">/fileTest/view.jsp</result>

</action>

<action name="downView" method="downView" class="com.fileTest.FileTestAction">

<result name="success" type="stream">

<!-- 반환값이 스트림. 해당파라미터에 대한 정보 -->

<param name="inputName">inputStream</param>

<param name="contentType">application/octet-stream</param>

<param name="contentDisposition">fileName=${orifinalFileName}</param>

<param name="bufferSize">1000000</param>

</result>

</action>

<action name="download" method="download" class="com.fileTest.FileTestAction">

<!-- 반환값이 null이므로 result는 기재하지 않음 -->

</action>

</package>

</struts>

12. struts properties

최대 파일 크기는 10메가 까지 가능

struts.i18n.encoding=UTF-8

struts.action.extension=action

struts.multipart.saveDir=c:\\temp

struts.multipart.maxSize=10000000

struts.configuration.files=struts-default.xml,struts.xml

업로드페이지

출력페이지

서버에 올라간 물리적 파일