java之文件上传二(源码)

基础知识在前面一篇,文件上传代码。耐心看到后面的重构,简洁多了
重构代码下载: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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值