java之文件上传二(源码)

来源:互联网 发布:网络信号增强器 编辑:程序博客网 时间:2024/05/04 11:05

基础知识在前面一篇,文件上传代码。耐心看到后面的重构,简洁多了
重构代码下载:http://download.csdn.net/detail/xiaozhegaa/9782629
(一) 开发思路:代码看起来有点乱,但是是有思路的

1:工厂–>对象设计模式。创建工厂—–>设置一下工厂的属性,其中涉及了临时文件,那么在源码第一二行先取得上传的真实路径和临时路径
2:得到对象,先设置上传文件的字符编码问题,然后判断是否是MIME协议提交
      > 3.1:若不是MIME协议提交,抛异常,提示说要用MIME提交,若不然就收集不到数据哦
      >> 3.2 : 若是MIME协议提交,则要把上传的内容转化成FileItemList。也就是用parseRequest()
4:取到list集合之后,循环遍历,判断是否是普通字段
      >> 5:如果是普通字段的话,那么采用一般的bean装在就可以 //user.getUsername(“xxx”)
      > > 6:否则就文件字段,那么对文件进行处理
7:这是扩展的功能:各种if
      >>7.1 :if(fileItem.endWith(“jpg”)) //上传是jpg,给不给通过
      >>7.2 :if(fileItem.getSize()==0) //空文件,给不给通过,还是抛异常
      > >7.3 :if(fileItem.gizeSize() > 1024 * 200) //文件大于200k,给不给通过
      > >7.4 :………等等
8:然后就读写数据,is.readLine(),os.write()。java基础固定写法
9:删除临时文件
10:显示上传成功页面

public class UploadServlet2 extends HttpServlet {    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        //取得上传的真实路径和临时路径        String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");        String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");        //使用第一个类u        //创建上传文件的工厂        DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();        //设置内存中的缓冲区大小。10k        fileItemFactory.setSizeThreshold(1024*10);        //设置上传文件临时存放的目录        fileItemFactory.setRepository(new File(tempPath));        //使用第二个类        //创建上传文件的对象        ServletFileUpload servletFileUpload = new ServletFileUpload(fileItemFactory);        //设置上传文件名字的字符编码        servletFileUpload.setHeaderEncoding("UTF-8");        //判断客户端是否是采用那个了mime协议去上传文件        boolean flag = servletFileUpload.isMultipartContent(request);        if(!flag){            //也就是不是采用mime的协议上传文件,那么抛异常。这里也可以采用一般的方式去处理哦哦            throw new ServletException();        }else{            /*也就是说是采用了MIME的协议上传文件             * 解析request中的所有上传内容,并且把每个内容解析成fileItem对象             * fileItem代表的是普通字段跟文件字段两类             */            try {                //使用第三个类                List<FileItem> fileItemList = servletFileUpload.parseRequest(request);                for(FileItem fileIem :fileItemList){                    if(fileIem.isFormField()){                        //如果说是普通的字段                        String fileName = fileIem.getFieldName();                        String fileValue = fileIem.getString("UTF-8");                        System.out.println(fileName+"-----"+fileValue);                    }else{                        //这里是文件上传字段                        String realFileName = fileIem.getName();                        /*                         * 对于ie浏览器的话上传路径是C:\Users\admin\Desktop\1.jpg,                         * 而对于一些高级浏览器火狐之类的路径是1.jpg。                            因此要对路径做一个处理。只需要1.jsp就可以                         */                        int index = realFileName.lastIndexOf("\\");                        if(index>=0){                            //确实是ie浏览器                            realFileName = realFileName.substring(index+1);                        }                        //通过真实的文件名换算出一个唯一的一个文件名                        String makeUuidFileName = makeUuidFileName(realFileName);                        //通过位运算换算出upload文件夹下面的子文件夹                        String makeUuidFilePath = makeUuidFilePath(uploadPath,makeUuidFileName);                        /*                        *在读取文件之前可以先进行一系列判断,如果判断不通过,不给提交                        *例如                        */                        //如果无上传文件                        if(fileItem.getSize()==0){                            throw new NoUpfileException();                        }                        //只能上传JPG文件                        if(!realFileName.endsWith("JPG")){                            throw new UpfileTypeException();                        }                        //只有上传<=200K的文件                        if(fileItem.getSize() > 200 * 1024){                            throw new UpfileSizeException();                        }                        //等等各种限制条件,自己写                        //获得到文件输入流                        InputStream is = fileIem.getInputStream();                        //取得文件输出流                        OutputStream os = new FileOutputStream(makeUuidFilePath+"/"+makeUuidFileName);                        byte[] buf = new byte[1024];                        int len = 0;                        while((len = is.read(buf)) > 0 ){                            os.write(buf, 0, len);;                        }                        is.close();                        os.close();                        //将上传文件的临时文件删除                        fileIem.delete();                        request.setAttribute("message", "上传成功");                        request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);                    }                }            } catch (FileUploadException e) {                e.printStackTrace();                request.setAttribute("message","上传文件失败");                request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request,response);            }           }       }    /**    *这个是防止说一个目录文件过多,采用&方式去推出二级目录之类的函数    */    private String makeUuidFilePath(String uploadPath, String makeUuidFileName) {        String uuidFilePath = null;        int code = makeUuidFileName.hashCode(); //获得到文件的hascode码  8        int dir1 = code & 0xF; //3        int dir2 = code & 0xF; //8        File file = new File(uploadPath+"/"+dir1+"/"+dir2);        if(!file.exists()){            //如果说文件路径不存在的话,那么就一次创建多个目录            file.mkdirs();        }        uuidFilePath = file.getPath();        return uuidFilePath;    }    /**     *写一个算法,给每一张图片起一个唯一的名字,这样在上传同一张图片的时候就可以有多个     * @param fileName 图片的名字,最后加上文件的名字识别     * @return     */    public String makeUuidFileName(String fileName){        return UUID.randomUUID().toString()+"_"+fileName;    }</font>

(二) 第一种重构的方式比较简单:也就是把原代码中能够抽取出来的方法,全部抽取出来放在一个UploadUtil类中,然后再原来的方法中调用该静态方法就可以

注意:这里的源码没有列举出来,只是列举方法名而已。具体的实现源码我已经导成了一个jar包。如果有兴趣的可以下载该jar包研究一下啊。或者学习者自己重构

//取得上传的真实路径和临时路径    public static final String tempPath = "/WEB-INF/temp";    public static final String uploadPath ="/WEB-INF/upload";    /*     * 对于ie浏览器的话上传路径是C:\Users\admin\Desktop\1.jpg,     * 而对于一些高级浏览器火狐之类的路径是1.jpg。        因此要对路径做一个处理。只需要1.jsp就可以     */    public static String getRealFileName(String realFileName){        //代码忽略了  return 1.jpg        return realFileName;    }    /**取得upload目录下面的子目录     * @param uploadPath  :upload     * @param makeUuidFileName : a.jpg     * @return   upload/8/8     */    public static String makeUuidFilePath(String uploadPath, String makeUuidFileName) {        //代码忽略了 返回 upload/8/8        return uuidFilePath;    }    /**     * 取得文件的uuid名字     *写一个算法,给每一张图片起一个唯一的名字,这样在上传同一张图片的时候就可以有多个     * @param fileName 图片的名字,最后加上文件的名字识别     * @return     */    public static String makeUuidFileName(String fileName){        return UUID.randomUUID().toString()+"_"+fileName;    }    /*    *文件保存,也就是Io流那个    */    public static void doSave(InputStream is,String makeUuidFilePath ,String  makeUuidFileName){        //代码忽略了 返回 true/false        return true/false    }

(三)第二种重构就更加的简洁了
只需要调用
UploadUtil.doUpload();
UploadUtil.doSave();
两个方法就可以实现保存。

这种简介的代码才是我们所追求的。

测试案例:    public void doPost(HttpServletRequest request, HttpServletResponse response)            throws Exception {        try {            User user = UploadUtil.doUpload(request);            String uploadPath = this.getServletContext().getRealPath(UploadUtil.uploadPath);                UploadUtil.doSave(user,uploadPath);            request.setAttribute("message", "上传成功");            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);        } catch (FileUploadException e) {            e.printStackTrace();            request.setAttribute("message", "上传失败");            request.getRequestDispatcher("/WEB-INF/message.jsp").forward(request, response);        }    }
    //第二种封装方式,把上传文件分装成javaBean    public static User doUpload(HttpServletRequest request) throws Exception{        //代码忽略了        return user;    }    //javaBean的保存文件    public static void doSave(User user,String uploadPath) throws IOException{        //代码忽略了    }

这里写图片描述

0 0