package fileuploadserver;
import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URLEncoder;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;import javax.servlet.ServletException;
 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.FileItemFactory;
 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 import org.apache.commons.fileupload.servlet.ServletFileUpload;public class UpLoadServlet extends HttpServlet{
     
     /**
      * 
      */
     private static final long serialVersionUID = 4365850368925338622L;    @Override
     protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
         doGet(req, resp);
     }
     
     @Override
     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          /* response.setContentType("text/html;charset=gb2312");
           response.setCharacterEncoding("utf-8");*/
           
           OutputStream outputStream = null;   
           InputStream inputStream = null;
           String url=request.getRequestURI();
           url=url.substring(url.lastIndexOf("/")+1, url.lastIndexOf("."));
           System.out.println("----:"+url);
           if("upload".equals(url)){
               System.out.println("上传");
               upload(request,response);
           }
           if("start".equals(url)){
               request.getRequestDispatcher("upload.jsp").forward(request, response);
           }
           if("end".equals(url)){
               download(request,response);
           }
           if("down".equals(url)){
               down(request,response);
           }
           if("test".equals(url)){
               request.getRequestDispatcher("test.jsp").forward(request, response);
           }
           
     }
     
     /**
      * 下载
      * @param request
      * @param response
      * @throws ServletException
      * @throws IOException
      */
     public void download(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{        // 实现思路:先获取upload目录下所有文件的文件名,再保存;跳转到down.jsp列表展示
         //1. 初始化map集合Map<包含唯一标记的文件名, 简短文件名>  ;
         Map<String,String> fileNames = new HashMap<String,String>();
         
         //2. 获取上传目录,及其下所有的文件的文件名
         //String basePath = getServletContext().getRealPath("/upload");
         String basePath = "e:\\upload";
         // 目录
         File file = new File(basePath);
         // 目录下,所有文件名
         String[] list = file.list();
         System.out.println(Arrays.toString(list));
         // 遍历,封装
         if (list != null && list.length > 0){
             for (int i=0; i<list.length; i++){
                 // 全名
                 String fileName = list[i];
                 // 短名
                 String shortName = fileName.substring(fileName.lastIndexOf("#")+1);
                 // 封装
                 fileNames.put(fileName, shortName);
             }
         }
         System.out.println("---fileNames:"+fileNames);
         // 3. 保存到request域
         request.setAttribute("fileNames", fileNames);
         // 4. 转发
         request.getRequestDispatcher("/down.jsp").forward(request, response);
     }
     /**
      * 上传
      * @param request
      * @param response
      */
     public void upload(HttpServletRequest request,HttpServletResponse response){
         /*********文件上传组件: 处理文件上传************/
         try {
             // 1. 文件上传工厂
             FileItemFactory factory = new DiskFileItemFactory();
             // 2. 创建文件上传核心工具类
             ServletFileUpload upload = new ServletFileUpload(factory);
 //            // 一、设置单个文件允许的最大的大小: 30M
 //            upload.setFileSizeMax(30*1024*1024);
 //            // 二、设置文件上传表单允许的总大小: 80M
 //            upload.setSizeMax(80*1024*1024);
             // 三、 设置上传表单文件名的编码
             // 相当于:request.setCharacterEncoding("UTF-8");
             upload.setHeaderEncoding("UTF-8");
             
             // 3. 判断: 当前表单是否为文件上传表单
             if (ServletFileUpload.isMultipartContent(request)){
                 // 4. 把请求数据转换为一个个FileItem对象,再用集合封装
                 List<FileItem> list = upload.parseRequest(request);
                 System.out.println("-----list:"+list+"----------size:"+list.size());
                 // 遍历: 得到每一个上传的数据
                 for (FileItem item: list){
                     // 判断:普通文本数据
                     if (item.isFormField()){
                         // 普通文本数据
                         String fieldName = item.getFieldName();    // 表单中元素名称
                         String content = item.getString();        // 表单中元素名称里所对应的数据
                         //item.getString("UTF-8");  指定编码
                         System.out.println(fieldName + " " + content);
                     }
                     // 上传文件(文件流) ----> 上传到upload目录下
                     else {
                         // 普通文本数据
                         String name = item.getName();            // 文件名,上传文件的名称                
                         String fieldName = item.getFieldName();    // 表单中的元素名称
                         String content = item.getString();        // 表单元素名称, 对应的数据,如果事文本就会返回文本,如果事二进制返回乱码
                         String type = item.getContentType();    // 文件类型,是图片,文本,压缩包等
                         InputStream in = item.getInputStream(); // 上传文件流
                         
                         /*
                          *  四、文件名重名
                          *  对于不同用户readme.txt文件,不希望覆盖!
                          *  后台处理: 给用户添加一个唯一标记!
                          */
                         // a. 随机生成一个唯一标记
                         String id = UUID.randomUUID().toString().replace("-", "");
                         name=name.substring(name.lastIndexOf("\\")+1);
                         // b. 与文件名拼接
                         name = id +"#"+ name;
                         System.out.println("-----name:"+name);
                         // 获取上传基路径
                         //String path = getServletContext().getRealPath("/upload");
                         String path = "e:\\upload";
                         // 创建目标文件
                         File file = new File(path,name);
                         
                         // 工具类,文件上传
                         item.write(file);
                         item.delete();   //删除系统产生的临时文件,这个是一个占内存的中转数据,没用,应该删除
                         System.out.println(path);
                     }
                     
                 }
                 
             }
             else {
                 System.out.println("当前表单不是文件上传表单,处理失败!");
             }
         } catch (Exception e) {
             e.printStackTrace();
         }
     }
     
     
     /**
      *  3. 处理下载
      */
     private void down(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         System.out.println("进入下载");
         // 获取用户下载的文件名称(url地址后追加数据,get)
         String fileName = request.getParameter("fileName");
         System.out.println("---fileName:"+fileName);
         //GET方式获得的汉字需要转码
 //        fileName = new String(fileName.getBytes("ISO8859-1"),"UTF-8");
         
         // 先获取上传目录路径
         //String basePath = getServletContext().getRealPath("/upload");
         String basePath = "e:\\upload";
         // 获取一个文件流
         InputStream in = new FileInputStream(new File(basePath,fileName));
         
         // 如果文件名是中文,需要进行url编码
         fileName = URLEncoder.encode(fileName, "UTF-8");
         // 设置下载的响应头
         response.setHeader("content-disposition", "attachment;fileName=" + fileName);
         
         // 获取response字节流
         OutputStream out = response.getOutputStream();
         byte[] b = new byte[1024];
         int len = -1;
         while ((len = in.read(b)) != -1){
             out.write(b, 0, len);
         }
         // 关闭
         out.close();
         in.close();
         
         
     }
 }