javaweb学习27:java文件上传

javaweb学习27:java文件上传

  • 文件上传流程:

     

     

  • 分析:

    • 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的;

    • 一般选择采用apache的开源工具:common-fileupload这个文件上传组件;

    • common-fileupload是依赖于common-io这个包的,所以还需要下载这个jar包;

 

  • 常用类介绍:文件上传调优

    • 为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放在web-inf目录下;

    • 为防止文件覆盖的现在发生,要为上传文件产生一个唯一的文件名

      • 解决方案:UUID,时间戳(MD5加密,但时间戳有可能重复)

    • 要限制上传文件的最大值;

    • 可以限制上传文件的类型,再收到上传文件名时,判断后缀是否合法;

       

  • 需要用到的类详解:

    • ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成为一个FileItem对象;

    • 在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象,所以,我们需要在进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法或setFileItemFactory()方法设置ServletFileUpload对象的fileItemFactory属性;

       

  • 开发步骤:

    • FileItem类:

      • 在HTML页面input必须有name:<input type="file" name="filename">

      • 表单如果包含一个文件上传输入项的话,这个表单的enctype属性必须设置为multipart/form-data

        <form action="" enctype="multipart/form-data" method="post" >
          上传用户:<input type="text" name="usernam"><br/>
           <p>
               <input type="file" name="file1">
           </p>
           <p>
               <input type="file" name="file2">
           </p>
           <p>
               <input type="submit"> |  <input type="reset">
           </p>
        </form>
      • 浏览器表单的类型如果为multipart/form-data,在服务器端想要获取数据就要通过流;

         

    • 常用方法介绍:

      • 常用方法:

        //isFormField方法用于判断FileItem类对象封装的数据是一个普通文本表单,还是一个文件表单;
        //如果是普通表单字段则返回true,否则返回false;
        boolean isFormField();
        //getFieldName方法用于返回表单标签name属性的值;
        String getFieldName();
        //getString方法用于将FileItem对象中保存的数据流内容以一个字符串返回;
        String getString();
        //getName方法用于获得文件上传字段中的文件名;
        String getName();
        //以流的形式返回文件上传的数据内容
        InputStream getInputStream();
        //delete方法用来清空Fileitem类对象中存放的主体内容;
        //如果主体内容被保存在临时文件中,delete方法将删除该临时文件;
        void delete();

         

    • ServletFileUpload类:

      • ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象中,使用parseRequest(HttpServletRequest)方法可以将通过表单中每一个HTML标签提交的数据封装成一个FileItem对象,然后以List列表的形式返回;使用该方法处理上传文件简单易用;

         

 

  • 代码案例:


    /**
    * 文件上传
    */
    public class FileServlet extends HttpServlet {
       protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

           System.out.println("-----开始处理------");
           //1,判断上传的文件是普通表单还是带文件的表单
           if(!ServletFileUpload.isMultipartContent(request)){
               return;//终止方法运行,说明这是一个普通的表单,直接返回
          }

           //2,创建文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件;
           String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
           File uploadFile = new File(uploadPath);
           if(!uploadFile.exists()){
               uploadFile.mkdir();//创建这个目录
          }

           //3,缓存,临时文件
           //临时路径,假如文件超过了预期的大小,我们就把他放在一个临时文件中,过几天自动删除,或者提醒用户转存为永久
           String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
           File tempFile = new File(uploadPath);
           if(!tempFile.exists()){
               tempFile.mkdir();//创建这个目录
          }

           //4,处理上传文件,一般都需要通过流来获取,我们可以使用request.getInputStream(),原生态的文件上传流获取,十分麻烦
           //但是我们都建议使用Apache的文件上传组件来实现,common-fileupload,它需要依赖于commons-io组件;

           /**
            * 处理开始:
            */
           try {
               //1,创建DiskFileItemFactory对象,处理文件上传路径或者大小限制的;
               DiskFileItemFactory factory= getDiskFileItemFactory(tempFile);
               //2,获取ServletFileUpload
               ServletFileUpload upload= getServletFileUpload(factory);
               //3,处理上传的文件
               String msg= null;
               msg = uploadParseRequest(upload,request,uploadPath);
               //4,servlet请求转发消息
               request.setAttribute("msg",msg);
               request.getRequestDispatcher("info.jsp").forward(request,response);
          } catch (FileUploadException e) {
               e.printStackTrace();
          }

      }

       //1
       public static DiskFileItemFactory getDiskFileItemFactory(File file){
           DiskFileItemFactory factory = new DiskFileItemFactory();
           //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中去
           factory.setSizeThreshold(1024*1024);//缓存区大小为1M
           factory.setRepository(file);//临时目录的保存目录,需要一个file
           return factory;

      }

       //2
       public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory){
           ServletFileUpload upload=new ServletFileUpload(factory);
           //监听文件上传进度
           upload.setProgressListener(new ProgressListener() {
               @Override
               public void update(long pBytesRead, long pContentLength, int pItems) {
                   System.out.println("总大小:"+pContentLength+"已上传:"+pBytesRead);
              }

          });

           //处理乱码问题
           upload.setHeaderEncoding("UTF-8");
           //设置单个文件的最大值
           //1024=1kb * 1024 =1M * 10=10M
           upload.setFileSizeMax(1024*1024*10);
           return upload;
      }


       //3
       public static String uploadParseRequest(ServletFileUpload upload,HttpServletRequest request,String uploadPath) throws FileUploadException, IOException {

           String msg="";

           //解析前端请求,封装成一个FileItem对象
           List<FileItem> fileItems = upload.parseRequest(request);
           //fileItems每一个表单对象
           for (FileItem fileItem : fileItems) {
               if(fileItem.isFormField()){//判断上传的文件是普通的表单还是带文件的表单
                   String name = fileItem.getFieldName();
                   String value = fileItem.getString("UTF-8");//处理乱码
                   System.out.println(name+":"+value);

              }else{//判断它是上传的文件

                   //=================处理文件================//

                   //拿到文件名字
                   String uploadFileName = fileItem.getName();
                   System.out.println("上传的文件名:"+uploadFileName);

                   if(uploadFileName.trim().equals("") || uploadFileName==null ){
                       continue;
                  }
                   //获得上传的文件名:/images/girl/demo.png
                   String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                   //获得文件名的后缀
                   String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);

                   /**
                    * 如果文件后缀名 fileExtName 不是我们所需要的
                    * 就直接return ,不处理,告诉用户文件类型不对;
                    */

                   System.out.println("文件信息[文件名为:"+fileName+" ;文件类型为:"+fileExtName+"]");

                   /**
                    * 网络传输的东西,都需要序列化:
                    * POJO:实体类,如果想要在多个电脑上运行,就需要传输,传输就需要把对象序列化
                    * implements java.io.Serializable :标记接口
                    * jni.h: java native interface java本地化接口
                    *
                    */
                   //可以使用UUID(唯一识别的通用码),保证文件名唯一;
                   //UUID.randomUUID(),随机生一个唯一识别的通用码;

                   String uuidPath = UUID.randomUUID().toString();

                   //=================存放地址================//

                   //存到哪?uploadPath
                   //文件真实存在的路径 realPath
                   String realPath=uploadPath+"/"+uuidPath;
                   //给每个文件创建一个对应的文件夹
                   File reaPathFile = new File(realPath);
                   if(!reaPathFile.exists()){
                       reaPathFile.mkdir();
                  }

                   //=================文件传输================//

                   //获得文件上传的流
                   InputStream inputStream = fileItem.getInputStream();
                   //创建一个文件输出流
                   FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName);
                   //创建一个缓冲区
                   byte[] buffer=new byte[1024];

                   //判断是否读取完毕
                   int len=0;

                   while ((len=inputStream.read(buffer))>0) {
                       fos.write(buffer,0,len);
                  }

                   //关闭流
                   fos.close();
                   inputStream.close();

                   msg="文件上传完毕";
                   fileItem.delete();//上传成功,清除临时文件

              }
          }

           return msg;

      }

       protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      }
    }

 

  • 代码案例:jsp请求

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
     <head>
       <title>文件上传</title>
     </head>
     <body>

    <%--通过表单上传文件
       get:文件大小有限制;
       post:无限制,
       
     --%>
     <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="POST" >
      上传用户:<input type="text" name="usernam"><br/>
       <p>
         <input type="file" name="file1">
       </p>
       <p>
         <input type="file" name="file2">
       </p>
       <p>
         <input type="submit"> |  <input type="reset">
       </p>


     </form>



     </body>
    </html>

     

  • 代码案例:web.xml

    <servlet>
       <servlet-name>FileServlet</servlet-name>
       <servlet-class>com.ljxdemo.test.FileServlet</servlet-class>
    </servlet>
    <servlet-mapping>
       <servlet-name>FileServlet</servlet-name>
       <url-pattern>/upload.do</url-pattern>
    </servlet-mapping>

     

 

 

 

 

 

 

posted @   gzs1024  阅读(191)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示