웹사이트 검색

서블릿 파일 업로드 및 파일 다운로드 예제


Servlet 파일 업로드 및 파일 다운로드는 최근 Java servlet에서 일반적인 작업입니다. 서버에 servlet 파일을 업로드한 다음 서버에서 클라이언트로 다운로드하는 샘플 예제를 제공하려고 생각했습니다.

서블릿 업로드 파일

서버에 파일을 업로드하는 Java용 HTML 페이지

서블릿에 게시 요청을 보내고 양식을 제출하여 서버에 파일을 업로드할 수 있습니다. 파일 업로드에 GET 방식을 사용할 수 없습니다. 주목해야 할 또 다른 점은 양식의 enctype이 multipart/form-data여야 한다는 것입니다. 사용자 파일 시스템에서 파일을 선택하려면 파일 형식의 입력 요소를 사용해야 합니다. 따라서 다음과 같이 파일을 업로드하기 위한 간단한 HTML 페이지 index.html을 가질 수 있습니다.

<html>
<head></head>
<body>
<form action="UploadDownloadFileServlet" method="post" enctype="multipart/form-data">
Select File to Upload:<input type="file" name="fileName">
<br>
<input type="submit" value="Upload">
</form>
</body>
</html>

파일 업로드를 위한 서버 파일 위치

파일을 서버의 일부 디렉토리에 저장해야 합니다. 이 디렉토리를 프로그램에 하드코딩할 수 있지만 더 나은 유연성을 위해 배치 설명자 컨텍스트 매개변수에서 구성 가능하도록 유지합니다. 또한 환영 파일 목록에 업로드 파일 html 페이지를 추가합니다. web.xml 파일은 다음과 같습니다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>ServletFileUploadDownloadExample</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <context-param>
    <param-name>tempfile.dir</param-name>
    <param-value>tmpfiles</param-value>
  </context-param>
</web-app>

파일 업로드 위치에 대한 ServletContextListener

파일 위치에 대한 컨텍스트 매개변수를 읽고 여기에서 File 객체를 생성해야 하므로 컨텍스트가 초기화될 때 이를 수행하도록 ServletContextListener를 작성할 수 있습니다. 절대 디렉토리 위치와 파일 객체를 다른 서블릿에서 사용할 컨텍스트 속성으로 설정할 수 있습니다. 우리의 ServletContextListener 구현 코드는 아래와 같습니다.

package com.journaldev.servlet;

import java.io.File;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class FileLocationContextListener implements ServletContextListener {

    public void contextInitialized(ServletContextEvent servletContextEvent) {
    	String rootPath = System.getProperty("catalina.home");
    	ServletContext ctx = servletContextEvent.getServletContext();
    	String relativePath = ctx.getInitParameter("tempfile.dir");
    	File file = new File(rootPath + File.separator + relativePath);
    	if(!file.exists()) file.mkdirs();
    	System.out.println("File Directory created to be used for storing files");
    	ctx.setAttribute("FILES_DIR_FILE", file);
    	ctx.setAttribute("FILES_DIR", rootPath + File.separator + relativePath);
    }

	public void contextDestroyed(ServletContextEvent servletContextEvent) {
		//do cleanup if needed
	}
	
}

파일 업로드 다운로드 서블릿

업데이트: Servlet Specs 3은 API에서 서버에 파일을 업로드하는 지원을 추가했으므로 타사 API를 사용할 필요가 없습니다. Servlet 3 업로드 파일을 확인하십시오. 파일 업로드의 경우 Apache Commons FileUpload 유틸리티를 사용합니다. 우리 프로젝트의 경우 버전 1.3을 사용하고 FileUpload는 Apache Commons IO jar에 의존하므로 위에서 볼 수 있듯이 프로젝트의 lib 디렉토리에 둘 다 배치해야 합니다. 프로젝트 구조 이미지. HttpServletRequest 개체를 구문 분석하고 FileItem 목록을 반환하는 메서드를 제공하는 DiskFileItemFactory 팩터리를 사용합니다. FileItem은 업로드해야 하는 파일의 파일 이름, 형식의 필드 이름, 크기 및 콘텐츠 유형 세부 정보를 가져오는 유용한 방법을 제공합니다. 디렉토리에 파일을 쓰려면 File 객체를 생성하고 FileItem write() 메서드에 인수로 전달하기만 하면 됩니다. 서블릿의 전체 목적은 파일을 업로드하는 것이므로 서블릿의 DiskFileItemFactory 개체 인스턴스를 초기화하기 위해 init() 메서드를 재정의합니다. doPost() 메서드 구현에서 이 개체를 사용하여 파일을 서버 디렉터리에 업로드합니다. 파일이 성공적으로 업로드되면 HTML 링크가 GET 메서드를 사용하므로 파일을 다운로드하기 위해 URL과 함께 클라이언트에 응답을 보냅니다. URL에 파일 이름에 대한 매개 변수를 추가하고 동일한 서블릿 doGet() 메서드를 활용하여 파일 다운로드 프로세스를 구현합니다. 다운로드 파일 서블릿을 구현하기 위해 먼저 파일에 대한 InputStream을 열고 ServletContext.getMimeType() 메서드를 사용하여 파일의 MIME 유형을 가져오고 이를 응답 콘텐츠 유형으로 설정합니다. 또한 응답 콘텐츠 길이를 파일 길이로 설정해야 합니다. 응답으로 파일을 보내고 있음을 클라이언트가 이해하도록 하려면 값이 \attachment;인 "Content-Disposition\ 헤더를 설정해야 합니다. filename="fileName”. 응답 구성 설정을 마치면 InputStream에서 파일 내용을 읽고 ServletOutputStream에 쓰고 출력을 클라이언트에 플러시할 수 있습니다. UploadDownloadFileServlet 서블릿의 최종 구현은 다음과 같습니다.

package com.journaldev.servlet;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

@WebServlet("/UploadDownloadFileServlet")
public class UploadDownloadFileServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
    private ServletFileUpload uploader = null;
	@Override
	public void init() throws ServletException{
		DiskFileItemFactory fileFactory = new DiskFileItemFactory();
		File filesDir = (File) getServletContext().getAttribute("FILES_DIR_FILE");
		fileFactory.setRepository(filesDir);
		this.uploader = new ServletFileUpload(fileFactory);
	}
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String fileName = request.getParameter("fileName");
		if(fileName == null || fileName.equals("")){
			throw new ServletException("File Name can't be null or empty");
		}
		File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileName);
		if(!file.exists()){
			throw new ServletException("File doesn't exists on server.");
		}
		System.out.println("File location on server::"+file.getAbsolutePath());
		ServletContext ctx = getServletContext();
		InputStream fis = new FileInputStream(file);
		String mimeType = ctx.getMimeType(file.getAbsolutePath());
		response.setContentType(mimeType != null? mimeType:"application/octet-stream");
		response.setContentLength((int) file.length());
		response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
		
		ServletOutputStream os = response.getOutputStream();
		byte[] bufferData = new byte[1024];
		int read=0;
		while((read = fis.read(bufferData))!= -1){
			os.write(bufferData, 0, read);
		}
		os.flush();
		os.close();
		fis.close();
		System.out.println("File downloaded at client successfully");
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		if(!ServletFileUpload.isMultipartContent(request)){
			throw new ServletException("Content type is not multipart/form-data");
		}
		
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.write("<html><head></head><body>");
		try {
			List<FileItem> fileItemsList = uploader.parseRequest(request);
			Iterator<FileItem> fileItemsIterator = fileItemsList.iterator();
			while(fileItemsIterator.hasNext()){
				FileItem fileItem = fileItemsIterator.next();
				System.out.println("FieldName="+fileItem.getFieldName());
				System.out.println("FileName="+fileItem.getName());
				System.out.println("ContentType="+fileItem.getContentType());
				System.out.println("Size in bytes="+fileItem.getSize());
				
				File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileItem.getName());
				System.out.println("Absolute Path at server="+file.getAbsolutePath());
				fileItem.write(file);
				out.write("File "+fileItem.getName()+ " uploaded successfully.");
				out.write("<br>");
				out.write("<a href=\"UploadDownloadFileServlet?fileName="+fileItem.getName()+"\">Download "+fileItem.getName()+"</a>");
			}
		} catch (FileUploadException e) {
			out.write("Exception in uploading file.");
		} catch (Exception e) {
			out.write("Exception in uploading file.");
		}
		out.write("</body></html>");
	}

}

서블릿 파일 다운로드 업로드 프로젝트 다운로드

아래 URL에서 Apache Commons IO jar 및 Apache Commons FileUpload jar를 다운로드할 수 있습니다. https://commons.apache.org/proper/commons-io/download_io.cgi

서블릿 파일 다운로드 업로드 예제 프로젝트 다운로드

서블릿 예외 처리에 대한 시리즈의 다음 기사를 확인하십시오.