package com.house365.web.util;

import com.house365.commons.system.FastDFSUtil;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.*;

/*
* @author xuning
* @version 1.00
*/
public class CKEditPicUpload extends HttpServlet {

    private static final long serialVersionUID = -8394974127538125544L;

    private static String baseDir;// CKEditor的根目录
    private static boolean debug = false;// 是否debug模式
    private static boolean enabled = false;// 是否开启CKEditor上传
    private static Hashtable allowedExtensions;// 允许的上传文件扩展名
    private static Hashtable deniedExtensions;// 阻止的上传文件扩展名
    private static SimpleDateFormat dirFormatter;// 目录命名格式:yyyyMM
    private static SimpleDateFormat fileFormatter;// 文件命名格式:yyyyMMddHHmmssSSS

    Logger logger = LoggerFactory.getLogger(CKEditPicUpload.class);

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html; charset=UTF-8");
        response.setHeader("Cache-Control", "no-cache");
        PrintWriter out = response.getWriter();

        // 从请求参数中获取上传文件的类型：File/Image/Flash
        String typeStr = request.getParameter("Type");
        if (typeStr == null) {
            typeStr = "File";
        }
        if (debug) {
            logger.debug(typeStr);
        }
        // 文件名和文件真实路径
        String fileUrl = "";
        if (enabled) {
            // 使用Apache Common组件中的fileupload进行文件上传
            FileItemFactory factory = new DiskFileItemFactory();
            ServletFileUpload upload = new ServletFileUpload(factory);
            try {
                List items = upload.parseRequest(request);
                Map fields = new HashMap();
                Iterator iter = items.iterator();
                while (iter.hasNext()) {
                    FileItem item = (FileItem) iter.next();
                    if (item.isFormField())
                        fields.put(item.getFieldName(), item.getString());
                    else
                        fields.put(item.getFieldName(), item);
                }
                // CEKditor中file域的name值是upload
                FileItem uplFile = (FileItem) fields.get("upload");
                // 获取文件名并做处理
                String fileNameLong = uplFile.getName();
                fileNameLong = fileNameLong.replace('\\', '/');
                String[] pathParts = fileNameLong.split("/");
                String fileName = pathParts[pathParts.length - 1];
                // 获取文件扩展名
                String ext = getExtension(fileName);
                // 获取文件名(无扩展名)
                if (extIsAllowed(typeStr, ext)) {
                    fileUrl = FastDFSUtil.uploadFileByStream(uplFile.getInputStream(), uplFile.getName());
                } else {
                    if (debug)
                        logger.debug("无效的文件类型： " + ext);
                }
            } catch (Exception ex) {
                logger.error(ex.getMessage(), ex);
            }
        } else {
            if (debug)
                logger.debug("未开启CKEditor上传功能");
        }
        // CKEditorFuncNum是回调时显示的位置，这个参数必须有
        String callback = request.getParameter("CKEditorFuncNum");
        out.println("<script type=\"text/javascript\">");
        out.println("window.parent.CKEDITOR.tools.callFunction(" + callback + ",'" + fileUrl + "',''" + ")");
        out.println("</script>");
        out.flush();
        out.close();
    }


    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }


    /**
     * 获取扩展名的方法
     */
    private String getExtension(String fileName) {
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    /**
     * 获取文件名的方法
     */
    private static String getNameWithoutExtension(String fileName) {
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    /**
     * Servlet初始化方法
     */
    public void init() throws ServletException {
        // 从web.xml中读取debug模式
        debug = (new Boolean(getInitParameter("debug"))).booleanValue();
        // 格式化目录和文件命名方式
        dirFormatter = new SimpleDateFormat("yyyyMM");
        fileFormatter = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        // 从web.xml中获取根目录名称
        baseDir = getInitParameter("baseDir");
        // 从web.xml中获取是否可以进行文件上传
        enabled = (new Boolean(getInitParameter("enabled"))).booleanValue();
        if (baseDir == null)
            baseDir = "/UserFiles/";
        String realBaseDir = getServletContext().getRealPath(baseDir);
        File baseFile = new File(realBaseDir);
        if (!baseFile.exists()) {
            baseFile.mkdirs();
        }
        // 实例化允许的扩展名和阻止的扩展名
        allowedExtensions = new Hashtable(3);
        deniedExtensions = new Hashtable(3);
        // 从web.xml中读取配置信息
        allowedExtensions.put("File", stringToArrayList(getInitParameter("AllowedExtensionsFile")));
        deniedExtensions.put("File", stringToArrayList(getInitParameter("DeniedExtensionsFile")));
        allowedExtensions.put("Image", stringToArrayList(getInitParameter("AllowedExtensionsImage")));
        deniedExtensions.put("Image", stringToArrayList(getInitParameter("DeniedExtensionsImage")));
        allowedExtensions.put("Flash", stringToArrayList(getInitParameter("AllowedExtensionsFlash")));
        deniedExtensions.put("Flash", stringToArrayList(getInitParameter("DeniedExtensionsFlash")));
    }

    /**
     * 字符串像ArrayList转化的方法
     */
    private ArrayList stringToArrayList(String str) {
        String[] strArr = str.split("\\|");
        ArrayList tmp = new ArrayList();
        if (str.length() > 0) {
            for (int i = 0; i < strArr.length; ++i) {
                tmp.add(strArr[i].toLowerCase());
            }
        }
        return tmp;
    }

    /**
     * 判断扩展名是否允许的方法
     */
    private boolean extIsAllowed(String fileType, String ext) {
        ext = ext.toLowerCase();
        ArrayList allowList = (ArrayList) allowedExtensions.get(fileType);
        ArrayList denyList = (ArrayList) deniedExtensions.get(fileType);
        if (allowList.size() == 0) {
            if (denyList.contains(ext)) {
                return false;
            } else {
                return true;
            }
        }
        if (denyList.size() == 0) {
            if (allowList.contains(ext)) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }


}
