org.exoplatform.upload.UploadService.java Source code

Java tutorial

Introduction

Here is the source code for org.exoplatform.upload.UploadService.java

Source

/**
 * Copyright (C) 2009 eXo Platform SAS.
 * 
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.exoplatform.upload;

import java.io.File;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.exoplatform.container.xml.InitParams;
import org.exoplatform.container.xml.PortalContainerInfo;
import org.gatein.common.logging.Logger;
import org.gatein.common.logging.LoggerFactory;

import java.io.FileOutputStream;
import java.io.InputStream;

public class UploadService {
    /** . */
    private static final Logger log = LoggerFactory.getLogger(UploadService.class);

    private Map<String, UploadResource> uploadResources = new LinkedHashMap<String, UploadResource>();

    private String uploadLocation_;

    private int defaultUploadLimitMB_;

    private Map<String, Integer> uploadLimitsMB_ = new LinkedHashMap<String, Integer>();

    public static String UPLOAD_RESOURCES_STACK = "uploadResourcesStack";

    public UploadService(PortalContainerInfo pinfo, InitParams params) throws Exception {
        String tmpDir = System.getProperty("java.io.tmpdir");
        if (params == null || params.getValueParam("upload.limit.size") == null)
            defaultUploadLimitMB_ = 0; // 0 means unlimited
        else
            defaultUploadLimitMB_ = Integer.parseInt(params.getValueParam("upload.limit.size").getValue());
        uploadLocation_ = tmpDir + "/" + pinfo.getContainerName() + "/eXoUpload";
        File uploadDir = new File(uploadLocation_);
        if (!uploadDir.exists())
            uploadDir.mkdirs();
    }

    /**
     * Create UploadResource for HttpServletRequest
     * 
     * @param request
     *           the webapp's {@link javax.servlet.http.HttpServletRequest}
     * @throws FileUploadException
     */
    @SuppressWarnings("unchecked")
    public void createUploadResource(HttpServletRequest request) throws FileUploadException {
        String uploadId = request.getParameter("uploadId");
        createUploadResource(uploadId, request);
    }

    public void createUploadResource(String uploadId, HttpServletRequest request) throws FileUploadException {
        UploadResource upResource = new UploadResource(uploadId);
        upResource.setFileName("");// Avoid NPE in UploadHandler
        uploadResources.put(upResource.getUploadId(), upResource);

        putToStackInSession(request.getSession(true), uploadId);

        double contentLength = request.getContentLength();
        upResource.setEstimatedSize(contentLength);
        if (isLimited(upResource, contentLength)) {
            upResource.setStatus(UploadResource.FAILED_STATUS);
            return;
        }

        ServletFileUpload servletFileUpload = makeServletFileUpload(upResource);
        // parse request
        List<FileItem> itemList = servletFileUpload.parseRequest(request);
        if (itemList == null || itemList.size() != 1 || itemList.get(0).isFormField()) {
            log.debug("Please upload 1 file per request");
            return;
        }

        DiskFileItem fileItem = (DiskFileItem) itemList.get(0);
        String fileName = fileItem.getName();
        if (fileName == null)
            fileName = uploadId;
        fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);
        String storeLocation = uploadLocation_ + "/" + uploadId + "." + fileName;

        // commons-fileupload will store the temp file with name *.tmp
        // we need to rename it to our desired name
        fileItem.getStoreLocation().renameTo(new File(storeLocation));

        upResource.setFileName(fileName);
        upResource.setMimeType(fileItem.getContentType());
        upResource.setStoreLocation(storeLocation);
        upResource.setStatus(UploadResource.UPLOADED_STATUS);
    }

    /**
     * @deprecated use {@link #createUploadResource(String, javax.servlet.http.HttpServletRequest)}  instead
     *
     */
    public void createUploadResource(String uploadId, String encoding, String contentType, double contentLength,
            InputStream inputStream) throws Exception {
        UploadResource upResource = new UploadResource(uploadId);
        RequestStreamReader reader = new RequestStreamReader(upResource);
        int limitMB = uploadLimitsMB_.get(uploadId).intValue();
        int estimatedSizeMB = (int) contentLength / 1024 / 1024;
        if (limitMB > 0 && estimatedSizeMB > limitMB) { // a limit set to 0 means unlimited
            upResource.setStatus(UploadResource.FAILED_STATUS);
            uploadResources.put(uploadId, upResource);
            log.debug("Upload cancelled because file bigger than size limit : " + estimatedSizeMB + " MB > "
                    + limitMB + " MB");
            return;
        }
        Map<String, String> headers = reader.parseHeaders(inputStream, encoding);

        String fileName = reader.getFileName(headers);
        if (fileName == null)
            fileName = uploadId;
        fileName = fileName.substring(fileName.lastIndexOf('\\') + 1);

        upResource.setFileName(fileName);
        upResource.setMimeType(headers.get(RequestStreamReader.CONTENT_TYPE));
        upResource.setStoreLocation(uploadLocation_ + "/" + uploadId + "." + fileName);
        upResource.setEstimatedSize(contentLength);
        uploadResources.put(upResource.getUploadId(), upResource);
        File fileStore = new File(upResource.getStoreLocation());
        if (!fileStore.exists())
            fileStore.createNewFile();
        FileOutputStream output = new FileOutputStream(fileStore);
        reader.readBodyData(inputStream, contentType, output);

        if (upResource.getStatus() == UploadResource.UPLOADING_STATUS) {
            upResource.setStatus(UploadResource.UPLOADED_STATUS);
            return;
        }

        uploadResources.remove(uploadId);
        fileStore.delete();
    }

    @SuppressWarnings("unchecked")
    private void putToStackInSession(HttpSession session, String uploadId) {
        Set<String> uploadResouceIds = (Set<String>) session.getAttribute(UploadService.UPLOAD_RESOURCES_STACK);
        if (uploadResouceIds == null) {
            uploadResouceIds = new HashSet();
        }
        uploadResouceIds.add(uploadId);
        session.setAttribute(UploadService.UPLOAD_RESOURCES_STACK, uploadResouceIds);
    }

    /**
     * Get UploadResource by uploadId
     * 
     * @param uploadId
     *           uploadId of UploadResource
     * @return org.exoplatform.upload.UploadResource of uploadId
     */
    public UploadResource getUploadResource(String uploadId) {
        return uploadResources.get(uploadId);
    }

    /**
     * Clean up temporary files that are uploaded in the Session but not removed yet
     * 
     * @param session
     */
    public void cleanUp(HttpSession session) {
        log.debug("Cleaning up uploaded files for temporariness");
        Set<String> uploadIds = (Set<String>) session.getAttribute(UploadService.UPLOAD_RESOURCES_STACK);
        if (uploadIds != null) {
            for (String id : uploadIds) {
                removeUploadResource(id);
                uploadLimitsMB_.remove(id);
            }
        }
    }

    /**
     * @deprecated use {@link #removeUploadResource(String)} instead
     * 
     * @param uploadId
     */
    @Deprecated
    public void removeUpload(String uploadId) {
        removeUploadResource(uploadId);
    }

    /**
     * Remove the UploadResource and its temporary file that associated with given <code>uploadId</code>.
     * <br/>If <code>uploadId</code> is null or UploadResource is null, do nothing
     * 
     * @param uploadId uploadId of UploadResource will be removed
     */
    public void removeUploadResource(String uploadId) {
        if (uploadId == null)
            return;
        UploadResource upResource = uploadResources.get(uploadId);
        if (upResource != null) {
            uploadResources.remove(uploadId);

            if (upResource.getStoreLocation() != null) {
                File file = new File(upResource.getStoreLocation());
                file.delete();
            }
        }

        // uploadLimitsMB_.remove(uploadId);
    }

    /**
     * Registry upload limit size for uploadLimitsMB_. If limitMB is null,
     * defaultUploadLimitMB_ will be registried
     * 
     * @param uploadId
     * @param limitMB
     *           upload limit size
     */
    public void addUploadLimit(String uploadId, Integer limitMB) {
        if (limitMB == null)
            uploadLimitsMB_.put(uploadId, Integer.valueOf(defaultUploadLimitMB_));
        else
            uploadLimitsMB_.put(uploadId, limitMB);
    }

    /**
     * Get all upload limit sizes
     * 
     * @return all upload limit sizes
     */
    public Map<String, Integer> getUploadLimitsMB() {
        return uploadLimitsMB_;
    }

    private ServletFileUpload makeServletFileUpload(final UploadResource upResource) {
        // Create a factory for disk-based file items
        DiskFileItemFactory factory = new DiskFileItemFactory();

        // Set factory constraints
        factory.setSizeThreshold(0);
        factory.setRepository(new File(uploadLocation_));

        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload(factory);
        ProgressListener listener = new ProgressListener() {
            public void update(long pBytesRead, long pContentLength, int pItems) {
                if (pBytesRead == upResource.getUploadedSize())
                    return;
                upResource.addUploadedBytes(pBytesRead - upResource.getUploadedSize());
            }
        };
        upload.setProgressListener(listener);
        return upload;
    }

    private boolean isLimited(UploadResource upResource, double contentLength) {
        // by default, use the limit set in the service
        int limitMB = defaultUploadLimitMB_;
        // if the limit is set in the request (specific for this upload) then use
        // this value instead of the default one
        if (uploadLimitsMB_.containsKey(upResource.getUploadId())) {
            limitMB = uploadLimitsMB_.get(upResource.getUploadId()).intValue();
        }

        double estimatedSizeMB = (contentLength / 1024) / 1024;
        if (limitMB > 0 && estimatedSizeMB > limitMB) { // a limit set to 0 means unlimited         
            if (log.isDebugEnabled()) {
                log.debug("Upload cancelled because file bigger than size limit : " + estimatedSizeMB + " MB > "
                        + limitMB + " MB");
            }
            return true;
        }
        return false;
    }
}