org.codelabor.system.file.web.servlet.FileUploadServlet.java Source code

Java tutorial

Introduction

Here is the source code for org.codelabor.system.file.web.servlet.FileUploadServlet.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.codelabor.system.file.web.servlet;

import static org.codelabor.system.dao.DAOConstants.AFFECTED_ROW_COUNT;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.security.InvalidParameterException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.anyframe.idgen.IdGenService;
import org.anyframe.util.properties.PropertiesService;
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.FileCleanerCleanup;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.codelabor.system.file.RepositoryType;
import org.codelabor.system.file.dto.FileDTO;
import org.codelabor.system.file.exception.InvalidRepositoryTypeException;
import org.codelabor.system.file.listener.FileUploadProgressListener;
import org.codelabor.system.file.manager.FileManager;
import org.codelabor.system.file.util.UploadUtils;
import org.codelabor.system.web.servlet.HttpRequestHeaderConstants;
import org.codelabor.system.web.servlet.HttpResponseHeaderConstants;
import org.codelabor.system.web.util.RequestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

/**
 * ?  
 * 
 * @author Shin Sang-jae
 * 
 */
public class FileUploadServlet extends HttpServlet {
    /**
     *   UID
     */
    private static final long serialVersionUID = 6060491747750865553L;
    /**
     * 
     */
    private final static Logger logger = LoggerFactory.getLogger(FileUploadServlet.class);

    /**
     *  
     */
    protected ServletConfig servletConfig;
    /**
     * ?
     */
    protected String parameterName;
    /**
     *  , ? 
     */
    protected String forwardPathUpload;
    /**
     *  , ? 
     */
    protected String forwardPathDownload;
    /**
     * ?  , ? 
     */
    protected String forwardPathList;
    /**
     * ? ? , ? 
     */
    protected String forwardPathRead;
    /**
     * ?  , ? 
     */
    protected String forwardPathDelete;

    /**
     * ?
     * 
     * @author Shin Sang-jae
     * 
     */
    public enum Parameter {
        upload, download, list, read, view, delete
    };

    /**
     * ? ?</br> ? UTF-8?.
     */
    protected String characterEncoding = "UTF-8";
    /**
     *  ? ? 
     */
    protected int sizeThreshold = DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD;
    /**
     * ?   ? ?</br> ? 10MB?.
     */
    protected long fileSizeMax = 1024 * 1024 * 10;
    /**
     *     ? ?</br> ? 100MB?.
     */
    protected long requestSizeMax = 1024 * 1024 * 100;
    /**
     * ?  </br> ?    user.dir  .
     */
    protected String realRepositoryPath = System.getProperty("user.dir");
    /**
     *  ?  </br> ?    java.io.tempdir?  .
     */
    protected String tempRepositoryPath = System.getProperty("java.io.tmpdir");
    /**
     * ?  ?</br> ? FILE_SYSTEM?.
     */
    protected RepositoryType repositoryType = RepositoryType.FILE_SYSTEM;

    /*
     * (non-Javadoc)
     * 
     * @see javax.servlet.GenericServlet#init(javax.servlet.ServletConfig)
     */
    @Override
    public void init(ServletConfig config) throws ServletException {
        // get init param
        servletConfig = config;
        parameterName = config.getInitParameter("parameterName");
        forwardPathUpload = config.getInitParameter("forwardPathUpload");
        forwardPathDownload = config.getInitParameter("forwardPathDownload");
        forwardPathList = config.getInitParameter("forwardPathList");
        forwardPathRead = config.getInitParameter("forwardPathRead");
        forwardPathDelete = config.getInitParameter("forwardPathDelete");

        // set service
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(config.getServletContext());

        PropertiesService propertiesService = (PropertiesService) ctx.getBean("propertiesService");

        // overwrite configuration
        characterEncoding = propertiesService.getString("file.default.character.encoding", characterEncoding);
        sizeThreshold = propertiesService.getInt("file.default.file.size.threshold", sizeThreshold);
        fileSizeMax = propertiesService.getLong("file.default.file.size.max", fileSizeMax);
        requestSizeMax = propertiesService.getLong("file.default.request.size.max", requestSizeMax);
        realRepositoryPath = propertiesService.getString("file.default.real.repository.path", realRepositoryPath);
        tempRepositoryPath = propertiesService.getString("file.default.temp.repository.path", tempRepositoryPath);
        repositoryType = RepositoryType.valueOf(
                propertiesService.getString("file.default.real.repository.type", repositoryType.toString()));
        // mkdirs
        File file = new File(realRepositoryPath);
        if (!file.exists()) {
            try {
                FileUtils.forceMkdir(file);
            } catch (IOException e) {
                StringBuilder sb = new StringBuilder();
                sb.append("Cannot make directory: ");
                sb.append(file.toString());
                logger.error(sb.toString());
                throw new ServletException(sb.toString());
            }
        }
        file = new File(tempRepositoryPath);
        if (!file.exists()) {
            try {
                FileUtils.forceMkdir(file);
            } catch (IOException e) {
                StringBuilder sb = new StringBuilder();
                sb.append("Cannot make directory: ");
                sb.append(file.toString());
                logger.error(sb.toString());
                throw new ServletException(sb.toString());
            }
        }

    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest
     * , javax.servlet.http.HttpServletResponse)
     */
    @Override
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            String parameterValue = request.getParameter(parameterName);
            switch (Parameter.valueOf(parameterValue)) {
            case upload:
                upload(request, response);
                break;
            case download:
                download(request, response);
                break;
            case view:
                view(request, response);
                break;
            case list:
                list(request, response);
                break;
            case delete:
                delete(request, response);
                break;
            case read:
                read(request, response);
                break;
            default:
                logger.error("Invalid parameter: {}", parameterValue);
                throw new InvalidParameterException(parameterValue);
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new IOException(e);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw new ServletException(e);
        }
    }

    /**
     * ? .
     * 
     * @param paramMap
     *            ? Map
     * @throws Exception
     *             
     */
    protected void processParameters(Map<String, Object> paramMap) throws Exception {
        logger.debug("paramMap: {}", paramMap.toString());
    }

    /**
     * ? .
     * 
     * @param request
     *            
     * @param response
     *            ?
     * @param path
     *            
     * @throws Exception
     *             
     */
    protected void dispatch(HttpServletRequest request, HttpServletResponse response, String path)
            throws Exception {
        logger.debug("dispatch path: ", path);
        RequestDispatcher dispatcher = servletConfig.getServletContext().getRequestDispatcher(path);
        dispatcher.forward(request, response);
    }

    /**
     * ??  .</br> ? ? ?? ?  , (: ?) ? mapId  . ?
     *  ?? ? repositoryType ,  ?
     * org.codelabor.system.file.RepositoryType .
     * 
     * @param request
     *            
     * @param response
     *            ?
     * @throws Exception
     *             
     */
    @SuppressWarnings("unchecked")
    protected void upload(HttpServletRequest request, HttpServletResponse response) throws Exception {
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(this.getServletContext());
        FileManager fileManager = (FileManager) ctx.getBean("fileManager");

        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        Map<String, Object> paramMap = RequestUtils.getParameterMap(request);
        logger.debug("paramMap: {}", paramMap.toString());

        String mapId = (String) paramMap.get("mapId");
        RepositoryType acceptedRepositoryType = repositoryType;
        String requestedRepositoryType = (String) paramMap.get("repositoryType");
        if (StringUtils.isNotEmpty(requestedRepositoryType)) {
            acceptedRepositoryType = RepositoryType.valueOf(requestedRepositoryType);
        }

        if (isMultipart) {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            factory.setSizeThreshold(sizeThreshold);
            factory.setRepository(new File(tempRepositoryPath));
            factory.setFileCleaningTracker(FileCleanerCleanup.getFileCleaningTracker(this.getServletContext()));

            ServletFileUpload upload = new ServletFileUpload(factory);
            upload.setFileSizeMax(fileSizeMax);
            upload.setSizeMax(requestSizeMax);
            upload.setHeaderEncoding(characterEncoding);
            upload.setProgressListener(new FileUploadProgressListener());
            try {
                List<FileItem> fileItemList = upload.parseRequest(request);
                Iterator<FileItem> iter = fileItemList.iterator();

                while (iter.hasNext()) {
                    FileItem fileItem = iter.next();
                    logger.debug("fileItem: {}", fileItem.toString());
                    FileDTO fileDTO = null;
                    if (fileItem.isFormField()) {
                        paramMap.put(fileItem.getFieldName(), fileItem.getString(characterEncoding));
                    } else {
                        if (fileItem.getName() == null || fileItem.getName().length() == 0)
                            continue;
                        // set DTO
                        fileDTO = new FileDTO();
                        fileDTO.setMapId(mapId);
                        fileDTO.setRealFilename(FilenameUtils.getName(fileItem.getName()));
                        if (acceptedRepositoryType == RepositoryType.FILE_SYSTEM) {
                            fileDTO.setUniqueFilename(getUniqueFilename());
                        }
                        fileDTO.setContentType(fileItem.getContentType());
                        fileDTO.setRepositoryPath(realRepositoryPath);
                        logger.debug("fileDTO: {}", fileDTO.toString());
                        UploadUtils.processFile(acceptedRepositoryType, fileItem.getInputStream(), fileDTO);
                    }
                    if (fileDTO != null)
                        fileManager.insertFile(fileDTO);
                }
            } catch (FileUploadException e) {
                e.printStackTrace();
                logger.error(e.getMessage());
                throw e;
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
                throw e;
            }
        } else {
            paramMap = RequestUtils.getParameterMap(request);
        }
        try {
            processParameters(paramMap);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
            throw e;
        }
        dispatch(request, response, forwardPathUpload);
    }

    /**
     *  ?? .
     * 
     * @return  ?
     * @throws Exception
     *             
     */
    protected String getUniqueFilename() throws Exception {
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(this.getServletContext());
        IdGenService uniqueFilenameGenerationService = (IdGenService) ctx
                .getBean("uniqueFilenameGenerationService");
        return uniqueFilenameGenerationService.getNextStringId();
    }

    /**
     * ? ?? .</br>? ??
     * org.codelabor.system.file.FileConstants.FILE_LIST_KEY?  attribute?
     * ??. Map Id?  ? Map Id
     * org.codelabor.system.file.FileConstants.MAP_ID?  attribute? ??.
     * 
     * @param request
     *            
     * @param response
     *            ?
     * @throws Exception
     *             
     */
    protected void list(HttpServletRequest request, HttpServletResponse response) throws Exception {
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(this.getServletContext());
        FileManager fileManager = (FileManager) ctx.getBean("fileManager");

        Map<String, Object> paramMap = RequestUtils.getParameterMap(request);
        logger.debug("paramMap: {}", paramMap.toString());

        String mapId = (String) paramMap.get("mapId");
        String repositoryType = (String) paramMap.get("repositoryType");

        IdGenService mapIdGenService = (IdGenService) ctx.getBean("sequenceMapIdGenService");

        List<FileDTO> fileDTOList = null;
        try {
            if (StringUtils.isEmpty(repositoryType)) {
                if (StringUtils.isEmpty(mapId)) {
                    fileDTOList = fileManager.selectFileAll();
                } else {
                    fileDTOList = fileManager.selectFileByMapId(mapId);
                }
            } else {
                switch (RepositoryType.valueOf(repositoryType)) {
                case DATABASE:
                    fileDTOList = fileManager.selectFileByRepositoryType(RepositoryType.DATABASE);
                    break;
                case FILE_SYSTEM:
                    fileDTOList = fileManager.selectFileByRepositoryType(RepositoryType.FILE_SYSTEM);
                    break;
                default:
                    logger.error("Invalid repository type: {}", repositoryType);
                    throw new InvalidRepositoryTypeException(repositoryType);
                }
            }
            request.setAttribute(org.codelabor.system.file.FileConstants.FILE_LIST_KEY, fileDTOList);
            request.setAttribute(org.codelabor.system.file.FileConstants.MAP_ID, mapIdGenService.getNextStringId());
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        dispatch(request, response, forwardPathList);
    }

    /**
     * ?? ??.
     * 
     * @param request
     *            
     * @param response
     *            ?
     * @throws Exception
     *             
     */
    protected void view(HttpServletRequest request, HttpServletResponse response) throws Exception {
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(this.getServletContext());
        FileManager fileManager = (FileManager) ctx.getBean("fileManager");

        Map<String, Object> paramMap = RequestUtils.getParameterMap(request);
        logger.debug("paramMap: {}", paramMap.toString());

        String fileId = (String) paramMap.get("fileId");

        StringBuilder sb = new StringBuilder();

        FileDTO fileDTO;
        fileDTO = fileManager.selectFileByFileId(fileId);
        logger.debug("fileDTO: {}", fileDTO);

        String repositoryPath = fileDTO.getRepositoryPath();
        String uniqueFilename = fileDTO.getUniqueFilename();
        String realFilename = fileDTO.getRealFilename();
        InputStream inputStream = null;
        if (StringUtils.isNotEmpty(repositoryPath)) {
            // FILE_SYSTEM
            sb.setLength(0);
            sb.append(repositoryPath);
            if (!repositoryPath.endsWith(File.separator)) {
                sb.append(File.separator);
            }
            sb.append(uniqueFilename);
            File file = new File(sb.toString());
            inputStream = new FileInputStream(file);
        } else {
            // DATABASE
            byte[] bytes = new byte[] {};
            if (fileDTO.getFileSize() > 0) {
                bytes = fileDTO.getBytes();
            }
            inputStream = new ByteArrayInputStream(bytes);

        }
        response.setContentType(fileDTO.getContentType());

        // set response contenttype, header
        String encodedRealFilename = URLEncoder.encode(realFilename, "UTF-8");
        logger.debug("realFilename: {}", realFilename);
        logger.debug("encodedRealFilename: {}", encodedRealFilename);
        logger.debug("character encoding: {}", response.getCharacterEncoding());
        logger.debug("content type: {}", response.getContentType());
        logger.debug("bufferSize: {}", response.getBufferSize());
        logger.debug("locale: {}", response.getLocale());

        BufferedInputStream bufferdInputStream = new BufferedInputStream(inputStream);
        ServletOutputStream servletOutputStream = response.getOutputStream();
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(servletOutputStream);
        int bytesRead;
        byte buffer[] = new byte[2048];
        while ((bytesRead = bufferdInputStream.read(buffer)) != -1) {
            bufferedOutputStream.write(buffer, 0, bytesRead);
        }
        // flush stream
        bufferedOutputStream.flush();

        // close stream
        inputStream.close();
        bufferdInputStream.close();
        servletOutputStream.close();
        bufferedOutputStream.close();
    }

    /**
     * ?? .</br> ?? ? Id ? fileId  .  
     * org.codelabor.system.daos.AFFECTED_ROW_COUNT?  attribute? ??.
     * 
     * @param request
     *            
     * @param response
     *            ?
     * @throws Exception
     *             
     */
    protected void delete(HttpServletRequest request, HttpServletResponse response) throws Exception {
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(this.getServletContext());
        FileManager fileManager = (FileManager) ctx.getBean("fileManager");

        int affectedRowCount = 0;

        // fileId 
        String[] fileIdList = request.getParameterValues("fileId");
        if (ArrayUtils.isEmpty(fileIdList)) {
            logger.warn("fileIdList is empty.");
        } else {
            try {
                affectedRowCount += fileManager.deleteFileByFileId(fileIdList);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
                throw e;
            }
        }

        // mapId 
        String[] mapIdList = request.getParameterValues("mapId");
        if (ArrayUtils.isEmpty(mapIdList)) {
            logger.warn("mapIdList is empty.");
        } else {
            try {
                affectedRowCount += fileManager.deleteFileByMapId(mapIdList);
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
                throw e;
            }
        }
        request.setAttribute(AFFECTED_ROW_COUNT, affectedRowCount);
        dispatch(request, response, forwardPathDelete);
    }

    /**
     * ?  .</br>? ?? ? Id ? fileID   ?? DTO
     * org.codelabor.system.file.FileConstants.FILE_KEY?  attribute? ??.
     * 
     * @param request
     *            
     * @param response
     *            ?
     * @throws Exception
     *             
     */
    protected void read(HttpServletRequest request, HttpServletResponse response) throws Exception {
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(this.getServletContext());
        FileManager fileManager = (FileManager) ctx.getBean("fileManager");
        String fileId = request.getParameter("fileId");
        FileDTO fileDTO = fileManager.selectFileByFileId(fileId);
        request.setAttribute(org.codelabor.system.file.FileConstants.FILE_KEY, fileDTO);
        dispatch(request, response, forwardPathRead);
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.servlet.GenericServlet#getServletConfig()
     */
    @Override
    public ServletConfig getServletConfig() {
        return this.servletConfig;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.servlet.Servlet#destroy()
     */
    @Override
    public void destroy() {
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.servlet.Servlet#getServletInfo()
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * ??  .
     * 
     * @param request
     *            
     * @param response
     *            ?
     * @throws Exception
     *             
     */
    protected void download(HttpServletRequest request, HttpServletResponse response) throws Exception {
        WebApplicationContext ctx = WebApplicationContextUtils
                .getRequiredWebApplicationContext(this.getServletContext());
        FileManager fileManager = (FileManager) ctx.getBean("fileManager");

        Map<String, Object> paramMap = RequestUtils.getParameterMap(request);
        logger.debug("paramMap: {}", paramMap.toString());

        String fileId = (String) paramMap.get("fileId");

        StringBuilder sb = new StringBuilder();

        FileDTO fileDTO;
        fileDTO = fileManager.selectFileByFileId(fileId);
        logger.debug("fileDTO: {}", fileDTO);

        String repositoryPath = fileDTO.getRepositoryPath();
        String uniqueFilename = fileDTO.getUniqueFilename();
        String realFilename = fileDTO.getRealFilename();
        InputStream inputStream = null;
        if (StringUtils.isNotEmpty(repositoryPath)) {
            // FILE_SYSTEM
            sb.setLength(0);
            sb.append(repositoryPath);
            if (!repositoryPath.endsWith(File.separator)) {
                sb.append(File.separator);
            }
            sb.append(uniqueFilename);
            File file = new File(sb.toString());
            inputStream = new FileInputStream(file);
        } else {
            // DATABASE
            byte[] bytes = new byte[] {};
            if (fileDTO.getFileSize() > 0) {
                bytes = fileDTO.getBytes();
            }
            inputStream = new ByteArrayInputStream(bytes);
        }

        // set response contenttype, header
        String encodedRealFilename = URLEncoder.encode(realFilename, "UTF-8");
        logger.debug("realFilename: {}", realFilename);
        logger.debug("encodedRealFilename: {}", encodedRealFilename);

        response.setContentType(org.codelabor.system.file.FileConstants.CONTENT_TYPE);
        sb.setLength(0);
        if (request.getHeader(HttpRequestHeaderConstants.USER_AGENT).indexOf("MSIE5.5") > -1) {
            sb.append("filename=");
        } else {
            sb.append("attachment; filename=");
        }
        sb.append(encodedRealFilename);
        response.setHeader(HttpResponseHeaderConstants.CONTENT_DISPOSITION, sb.toString());

        logger.debug("header: {}", sb.toString());
        logger.debug("character encoding: {}", response.getCharacterEncoding());
        logger.debug("content type: {}", response.getContentType());
        logger.debug("bufferSize: {}", response.getBufferSize());
        logger.debug("locale: {}", response.getLocale());

        BufferedInputStream bufferdInputStream = new BufferedInputStream(inputStream);
        ServletOutputStream servletOutputStream = response.getOutputStream();
        BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(servletOutputStream);
        int bytesRead;
        byte buffer[] = new byte[2048];
        while ((bytesRead = bufferdInputStream.read(buffer)) != -1) {
            bufferedOutputStream.write(buffer, 0, bytesRead);
        }
        // flush stream
        bufferedOutputStream.flush();

        // close stream
        inputStream.close();
        bufferdInputStream.close();
        servletOutputStream.close();
        bufferedOutputStream.close();
    }
}