eionet.gdem.utils.MultipartFileUpload.java Source code

Java tutorial

Introduction

Here is the source code for eionet.gdem.utils.MultipartFileUpload.java

Source

/**
 * License Version 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 *
 * The Original Code is "EINRC-7 / GDEM project".
 *
 * The Initial Developer of the Original Code is TietoEnator.
 * The Original Code code was developed for the European
 * Environment Agency (EEA) under the IDA/EINRC framework contract.
 *
 * Copyright (C) 2000-2004 by European Environment Agency.  All
 * Rights Reserved.
 *
 * Original Code: Enriko Ksper (TietoEnator)
 */

package eionet.gdem.utils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

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;

import eionet.gdem.GDEMException;

/**
 * Provides methods for uploading file from the client computer to the server. using commons-fileupload-0.1.jar
 *
 * File is uploaded to the same computer, where the servlet engine is running. File content is transferred using MIME-multipart HTTP
 * request.
 *
 * @author Enriko Ksper
 * @author George Sofianos
 */
public class MultipartFileUpload {

    // Objects for synchronizing file locking and session locking
    // private static Object fileLock = new Object();
    // private static Object SessionIdLock = new Object();

    // integer for generating unique name for temporary file
    // private static int HOW_LONG = 6;
    private static final String DEFAULT_ENCODING = "UTF-8";

    /** tmp folder for files. */
    private String _folderName;
    private String _fileName;
    private FileItem _fileItem;
    private DiskFileItemFactory factory = null;
    private ServletFileUpload upload;
    private boolean _uploadAtOnce = true;

    private HashMap _params = null;
    private List fileItems = null;
    private String encoding = null;
    private HashMap fileNameEscapes = new HashMap();
    private static char[] restrictedChars = { '\\', '/', ':', '*', '?', '"', '<', '>', '|', '\'', '&', '%', '#',
            ';' };

    /**
     * Constructor. Creates a new FileUploadAdapter object
     * @param uploadAtOnce Upload at once
     */
    public MultipartFileUpload(boolean uploadAtOnce) {

        // Create a factory for disk-based file items
        factory = new DiskFileItemFactory();

        // Create a new file upload handler
        upload = new ServletFileUpload(factory);
        _params = new HashMap();
        initEscapes();
        this._uploadAtOnce = uploadAtOnce;
    }

    /**
     * Default constructor
     */
    public MultipartFileUpload() {
        new MultipartFileUpload(true);
    }

    /**
     * Sets folder name where to insert uploaded file.
     *
     * @param fldName - folder for the uploaded file
     */
    public void setFolder(String fldName) {
        _folderName = fldName;
    }

    /**
     *
     */
    public HashMap getRequestParams() {
        return _params;
    }

    /**
     * Returns filename from request.
     */
    public String getFileName() {
        return _fileName;
    }

    public void setFileName(String name) {
        _fileName = name;
    }

    /**
     * Checks whether file with the specified filename already exists in the destination folder.
     */
    public boolean getFileExists() {

        if (_fileName == null || _folderName == null)
            return false;

        File file = new File(_folderName, _fileName);

        if (file == null)
            return false;

        return file.exists();

    }

    /**
     * @param request
     *            Servlet request
     * @throws GDEMException
     *             If an error occurs
     */
    public void processMultiPartRequest(HttpServletRequest request) throws GDEMException {

        List items = null;
        setEncoding(request.getCharacterEncoding());
        try {
            items = upload.parseRequest(request);
        } catch (FileUploadException fue) {
            throw new GDEMException(fue.toString());
        }

        Iterator iter = items.iterator();
        while (iter.hasNext()) {
            FileItem item = (FileItem) iter.next();
            // String itemName = item.getName();
            String fieldName = item.getFieldName();
            // String id = (String) this.parameterNames.get(fieldName);

            /*
             * System.out.println("Multipart item name is: " + itemName + " and fieldname is: " + fieldName); // + " and id is: " +
             * id); System.out.println("Is formfield: " + item.isFormField()); System.out.println("Content: " + item.getString());
             */
            if (item.isFormField()) {
                // It's a field name, it means that we got a non-file
                // form field. Upload is not required.
                String itemValue = null;
                try {
                    // use encoding from request
                    itemValue = item.getString(getEncoding());
                } catch (UnsupportedEncodingException e) {
                    // use default encoding
                    itemValue = item.getString();
                }

                if (_params.containsKey(fieldName)) {
                    Object curObj = _params.get(fieldName);
                    List valueList = null;

                    if (curObj instanceof String) {
                        valueList = new ArrayList();
                        valueList.add((String) curObj);
                    } else if (curObj instanceof List) {
                        valueList = (List) curObj;
                    }
                    valueList.add(itemValue);
                    _params.put(fieldName, valueList);
                } else {
                    _params.put(fieldName, itemValue);
                }
            } else {
                _fileItem = item;
                addFileItem(_fileItem);
                String fileName = getFileItemName(_fileItem.getName());
                setFileName(fileName);
                if (_uploadAtOnce)
                    saveFile();
            }
        }
    }

    /**
     * Stores uploaded file in the filesystem with the original filename. If the file with the same name exisits, appends next
     * available number at the end of the filename.
     *
     * @return File name
     *
     * @throws GDEMException Thrown in case of missing data or error during file writing.
     */
    public String saveFile() throws GDEMException {

        String fileName = getFileName();

        if (_folderName == null)
            throw new GDEMException("Folder name is empty!");
        if (fileName == null)
            throw new GDEMException("File name is empty!");
        if (_fileItem == null)
            throw new GDEMException("No files found!");
        factory.setRepository(new File(_folderName));

        if (_fileItem.getSize() == 0)
            return null; // There is nothing to save, file size is 0

        File file = new File(_folderName, fileName); // getUniqueFile(_folderName, fileName);
        fileName = file.getName();

        if (_fileItem.getSize() > 0) {
            try {
                _fileItem.write(file);
            } catch (Exception e) {
                throw new GDEMException(e.toString());
            }
        }
        return fileName;
    }

    /**
     * Stores uploaded file in the filesystem with specified name. Renames the existing file, if needed. Otherwise overwrites
     * exisitng file
     *
     * @param saveAs Destination file name.
     * @param keepExisting true, if rename existing file before saving the new faile. false, if overwrite exisitng file
     * @throws GDEMException Thrown in case of missing data or error during file writing.
     */
    public void saveFileAs(String saveAs, boolean keepExisting) throws GDEMException {

        File file = null;

        if (_folderName == null)
            throw new GDEMException("Folder name is empty!");
        if (_fileItem == null)
            throw new GDEMException("No files found!");

        factory.setRepository(new File(_folderName));

        if (_fileItem.getSize() == 0)
            return; // There is nothing to save, file size is 0

        if (saveAs == null)
            saveAs = getFileName();

        file = new File(_folderName, saveAs);

        if (file.exists()) {
            if (keepExisting) {
                File uniqueFile = getDateAappendedFile(_folderName, saveAs);
                file.renameTo(uniqueFile);
            }
        }

        if (_fileItem.getSize() > 0) {
            try {
                _fileItem.write(file);
            } catch (Exception e) {
                throw new GDEMException(e.toString());
            }
        }
    }

    /**
     * Generates filename.
     *
     * @param fileName File name
     * @param n set larger than 0, if file with the same name already exists in the tmp folder ex: genFileName( test.xls, 1 )= test_1.xls
     *            genFileName( test_1.xls, 2 )= test_2.xls
     */
    public static String getGeneratedFileName(String fileName, int n) {
        String ret;
        int pos = fileName.lastIndexOf(".");

        int dashPos = fileName.lastIndexOf("_");
        if (dashPos > 1 && dashPos < pos) {
            String snum = fileName.substring(dashPos + 1, pos);
            try {
                int inum = Integer.parseInt(snum);
                ret = fileName.substring(0, dashPos) + "_" + (inum + 1) + fileName.substring(pos);
            } catch (Exception e) {
                ret = fileName.substring(0, pos) + "_" + n + fileName.substring(pos);
            }
        } else {
            ret = fileName.substring(0, pos) + "_" + n + fileName.substring(pos);
        }

        return ret;
    }

    /**
     * Finds unique filename using genFileName method.
     *
     * @param folderName
     *            Folder where the file will be stored
     * @param fileName
     *            File name that should be used for generating the unique filename
     *
     * @return Filename that does not exist in the folder
     */
    public static File getUniqueFile(String folderName, String fileName) {

        int n = 0;
        File file = new File(folderName, fileName);
        while (file.exists()) {
            n++;
            fileName = getGeneratedFileName(fileName, n);
            file = new File(folderName, fileName);
        }

        return file;
    }

    /**
     * Returns unique file name
     * @param folderName Directory name
     * @param fileName File name
     * @return Unique file name
     */
    public static String getUniqueFileName(String folderName, String fileName) {
        File file = getUniqueFile(folderName, fileName);
        String strFileName = file.getName();
        return strFileName;
    }

    /**
     * Returns filename from filename with full path in: "C:\TEMP\test.txt" out: "test.txt".
     * @param fileName File name
     */
    private String getFileItemName(String fileName) {
        int i = fileName.lastIndexOf("\\");
        if (i < 0 || i >= fileName.length() - 1) {
            i = fileName.lastIndexOf("/");
            if (i < 0 || i >= fileName.length() - 1)
                return getEscapedItemName(fileName);
        }

        // fileName = Utils.escapeFileNsame(fileName.substring(i + 1));
        fileName = fileName.substring(i + 1);
        return getEscapedItemName(fileName);
    }

    /**
     * Appends current date value at the end of the filename.
     *
     * @param folderName
     *            Folder where the file will be stored
     * @param fileName
     *            File name that should be used for generating the unique filename
     *
     * @return Filename with appended date (in format yyMMddHHmmss)
     */
    private File getDateAappendedFile(String folderName, String fileName) {

        SimpleDateFormat sdf = new SimpleDateFormat();
        sdf.applyPattern("yyMMddHHmmss");
        String dateVal = sdf.format(new Date());

        int pos = fileName.lastIndexOf(".");
        StringBuffer buf = new StringBuffer();
        buf.append(fileName.substring(0, pos));
        buf.append("_");
        buf.append(dateVal);
        buf.append(fileName.substring(pos));

        return getUniqueFile(folderName, buf.toString());

    }

    /**
     * Stores fileItems into list.
     * @param item Item
     */
    private void addFileItem(FileItem item) {
        if (fileItems == null)
            fileItems = new ArrayList();

        fileItems.add(item);

    }

    /**
     * returns file item for sepcified fieldName.
     * @param fieldName Field name
     */
    private FileItem getFileItem(String fieldName) {
        if (fileItems == null)
            fileItems = new ArrayList();

        for (int i = 0; i < fileItems.size(); i++) {
            FileItem item = (FileItem) fileItems.get(i);
            if (item.getFieldName().equalsIgnoreCase(fieldName))
                return item;
        }

        return null;

    }

    /**
     * returns the file name for specified fieldName. Useful for posting several fileitems.
     *
     * @param fieldName
     *            - file item field name
     * @return
     */
    public String getFileName(String fieldName) {
        String strRet = null;

        if (fileItems == null || fieldName == null)
            return strRet;

        for (int i = 0; i < fileItems.size(); i++) {
            FileItem item = (FileItem) fileItems.get(i);
            if (item.getFieldName().equalsIgnoreCase(fieldName))
                return getFileItemName(item.getName());
        }
        return strRet;
    }

    /**
     * Stores uploaded file in the filesystem with the original filename. If the file with the same name exisits, appends next
     * available number at the end of the filename.
     *
     * @param fieldName
     *            - file item field name
     * @param folderName
     *            - target folder
     *
     * @return File name
     * @throws GDEMException
     *             Thrown in case of missing data or error during file writing.
     */
    public String saveFile(String fieldName, String folderName) throws GDEMException {

        folderName = (folderName == null) ? _folderName : folderName;
        if (folderName == null)
            throw new GDEMException("Folder name is empty!");

        FileItem fileItem = getFileItem(fieldName);
        if (fileItem == null)
            throw new GDEMException("No files found!");

        String fileName = getFileItemName(fileItem.getName());
        if (fileName == null)
            throw new GDEMException("File name is empty!");

        factory.setRepository(new File(folderName));

        if (fileItem.getSize() == 0)
            return null; // There is nothing to save, file size is 0

        File file = getUniqueFile(folderName, fileName);
        fileName = file.getName();

        if (fileItem.getSize() > 0) {
            try {
                fileItem.write(file);
            } catch (Exception e) {
                throw new GDEMException(e.toString());
            }
        }
        return fileName;
    }

    /**
     * Returns file as InputStream
     * @param fieldName Field name
     * @return InputStream
     * @throws GDEMException If an error occurs.
     * @throws IOException If an error occurs.
     */
    public InputStream getFileAsInputStream(String fieldName) throws GDEMException, IOException {

        FileItem fileItem = getFileItem(fieldName);
        if (fileItem == null)
            throw new GDEMException("No files found!");

        if (fileItem.getSize() == 0)
            throw new GDEMException("File size is 0KB!"); // There is nothing to save, file size is 0

        return fileItem.getInputStream();
    }

    /**
     * Gets encoding
     * @return Encoding
     */
    public String getEncoding() {
        if (encoding == null)
            encoding = DEFAULT_ENCODING;
        return encoding;
    }

    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    public String getFolderName() {
        return this._folderName;
    }

    /**
     * Returns escaped item name
     * @param itemName Item name
     * @return Escaped item name
     */
    private String getEscapedItemName(String itemName) {
        String fileItemName = null;
        try {
            // use encoding from request
            fileItemName = new String(itemName.getBytes(), getEncoding());
        } catch (UnsupportedEncodingException e) {
            // use default encoding
            fileItemName = itemName;
        }
        return parseFileName(fileItemName);

    }

    /**
     * Removes strange symbols from file name
     *
     * @param fileName File name
     * @return Processed file name
     */
    private String parseFileName(String fileName) {
        StringBuffer ret = new StringBuffer();

        int code = 0;
        int lastCode = 0;

        for (int i = 0; i < fileName.length(); i++) {
            char c = fileName.charAt(i);
            code = Character.valueOf(fileName.charAt(i));
            if (code == 63 && lastCode == 65533) {
                ret.append("s");
            } else if (fileNameEscapes.containsKey(new Integer(code))) {
                ret.append(fileNameEscapes.get(code));
            } else if (code > 127 || isRestrictedChar(c)) {
                ret.append("-");
            } else {
                ret.append(c);
            }
            // System.out.println(c + "=" + code);
            lastCode = code;
        }
        return ret.toString();
    }

    /**
     * Populates escaped characters list
     *
     */
    private void initEscapes() {
        fileNameEscapes.put(352, "S");
        fileNameEscapes.put(381, "Z");
        fileNameEscapes.put(382, "z");
        fileNameEscapes.put(252, "u");
        fileNameEscapes.put(245, "o");
        fileNameEscapes.put(246, "o");
        fileNameEscapes.put(228, "a");
        fileNameEscapes.put(213, "O");
        fileNameEscapes.put(214, "O");
        fileNameEscapes.put(196, "A");
    }

    /**
     * Checks if character is restricted.
     * @param c Character
     * @return True if character is restricted
     */
    private boolean isRestrictedChar(char c) {
        for (int i = 0; i < restrictedChars.length; i++) {
            if (c == restrictedChars[i])
                return true;
        }
        return false;
    }
}