多种方式实现文件上传

作者: 大炮对着虫子 | 来源:发表于2017-09-15 10:29 被阅读100次

    在servlet2.5中,我们实现文件上传功能,一般都会去借助第三方的插件,但在servlet 3.0 中提供了对文件上传的支持,我们再也无需去导入第三方的插件,就能够调用servlet 3.0 自身的api 实现文件上传功能。

    文件上传可以分为同步上传和异步上传,当然网上还有一些关于上传的插件可供使用,这里我分别讲述下。

    同步实现上传
    同步上传效果图

    jsp界面代码:

     <form action="${pageContext.request.contextPath}/UploadServlet"
                     method="post" enctype="multipart/form-data">
                     
                     上传文件:
                     <input type="file" name="file" id="file" accept=".jpg" multiple>
                     <br>
                     <input type="submit" value="上传">
                 </form>
    

    我们前端使用 type="file"标签进行二进制文件传输,在后台使用注解@MultipartConfig 标记servlet解析文件读取part。

    这是在servlet 3.0以后才能支持哦

    @MultipartConfig(maxFileSize=1024*1024*5)//标识Servlet支持文件上传,设置约束,最大上传5M
    

    当我们上传文件的时候,需要考虑给文件重命名,以及以日为单位建立个文件夹进行图片的存储。
    首先,建立文件夹(两个,一个总的存储文件夹,一个存储一天的文件夹)

    public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
                 request.setCharacterEncoding("utf-8");
                 response.setCharacterEncoding("utf-8");
                 response.setContentType("text/html;charset=utf-8");
                 //存储路径物理路径
                String savePath = request.getServletContext().getRealPath("/uploadFile");
                //得到当前日期,每天一个以日期命名文件夹,方便管理
                String crtdate = DateUtils.format(new Date(), "yyyyMMdd");
                String dirc = savePath+File.separator+crtdate;
             // 创建目录
                File uploadDir = new File(dirc);
                if (uploadDir.getParentFile() != null || !uploadDir.getParentFile().isDirectory()) {
                    //创建目录6
                    uploadDir.getParentFile().mkdirs();
                    if (!uploadDir.exists()) {
                        uploadDir.mkdir();
                    }
                }
    

    接下来是将jsp传递过来的文件上传到指定路径,采用Part进行上传,期间当然需要对 文件进行改名字。

        //获取上传的文件集合
                 Collection<Part> parts = request.getParts();
                //上传单个文件
                if (parts.size()==1) {
                    //Servlet3.0将multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作。
                    //Part part = parts[0];//从上传的文件集合中获取Part对象
                    Part part = request.getPart("file");//通过表单file控件(<input type="file" name="file">)的名字直接获取Part对象
                   //Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
                    //获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
                    String header = part.getHeader("content-disposition");
                    //获取文件名aaa.aa.bb.jpg
                    String fileName = getNewName(getFileName(header));
                    String imgurl = dirc+File.separator+fileName;
                    //把文件写到指定路径
                    part.write(imgurl);
                   
                }else {
                    //一次性上传多个文件
                    for (Part part : parts) {//循环处理上传的文件
                        //获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
                        String header = part.getHeader("content-disposition");
                        //获取文件名
                       String fileName = getNewName(getFileName(header));
                       //把文件写到指定路径
                       part.write(savePath+File.separator+fileName);
                  }
                }
               PrintWriter out = response.getWriter();
               out.println("上传成功");
               out.flush();
               out.close();
    

    因为需要对文件进行重命名,所以需要获取到文件名,好截取文件的格式,Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来。
    String header = part.getHeader("content-disposition");

     /**
         * 根据请求头解析出文件名
         * 请求头的格式:火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip"
         *                 IE浏览器下:form-data; name="file"; filename="E:\snmp4j--api.zip"
         * @param header 请求头
         * @return 文件名
         */
        public String getFileName(String header) {
             /**
             * String[] tempArr1 = header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别
             * 火狐或者google浏览器下:tempArr1={form-data,name="file",filename="snmp4j--api.zip"}
             * IE浏览器下:tempArr1={form-data,name="file",filename="E:\snmp4j--api.zip"}
             */
            String[] tempArr1 = header.split(";");
             /**
              *火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}
              *IE浏览器下:tempArr2={filename,"E:\snmp4j--api.zip"}
              */
             String[] tempArr2 = tempArr1[2].split("=");
            //获取文件名,兼容各种浏览器的写法
             String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\")+1).replaceAll("\"", "");
             return fileName;
        }
         
    

    获取到文件名之后,就可以自己截取后缀名然后与时间System.currentTimeMillis()进行拼接,则可以得到一个随机唯一的数字,如果考虑高并发的情况下,要确保唯一,可以在名字里在加上一位随机数。

    到目前,就实现了同步的文件上传功能。

    formdata异步实现文件上传

    首先看下jsp界面:

    <form id= "uploadForm">  
    
    
          <p >图片作者: <input type="text" name="filename" value= ""/></p >  
           <p >图片描述: <input type="text" name="filesay" value= ""/></p >  
          <p >上传文件: <input type="file" name="file"/></ p>  
          <input type="button" value="上传" onclick="doUpload()" />  
    </form>  
        
        <script type="text/javascript">
        function doUpload(){
            //封装FormData(dom对象)
            var deptForm = $("#uploadForm")[0];
            var formdata = new FormData(deptForm);
            $.ajax({
                url:"${pageContext.request.contextPath}/AjaxUploadServlet",
                type:"post",
                data: formdata,
                //dataType:"json",
                contentType: false, //3.必须false才会避开jQuery对 formdata 的默认处理, XMLHttpRequest会对 formdata 进行正确的处理 
                processData: false, //4.必须false才会自动加上正确的Content-Type
                success:function(data){
                    console.info(data);
                    //location.href = "sss.servlet";//同步跳转
                },
                error:function(){
                    alert("出错了!");
                }
            });
        }
            
        </script>
    

    需要注意的是,使用var formdata=new FormData(Dom元素); 传递的是一个Dom元素而不是一个JQ对象。

    使用formdata时,需要在servlet加上注解的支持。不然servlet通过request是获取不到值的

    @MultipartConfig(maxFileSize=1024*1024*8)
    

    创建文件夹,主文件夹(uploadFile)包含所有上传文件

    以日为单位创建日文件夹,存放当日上传文件。
    定义一个bean,将前台界面传过来的参数以及上传图片的路径存储在bean里面,传递给dao层,进行数据库存储,实现持久化。

     request.setCharacterEncoding("utf-8");
             response.setCharacterEncoding("utf-8");
             response.setContentType("text/html;charset=utf-8");
             
             //存储路径物理路径
             String savePath = request.getServletContext().getRealPath("/uploadFile");
             //得到当前日期,每天一个以日期命名文件夹,方便管理
             String crtdate = DateUtils.format(new Date(), "yyyyMMdd");
             String dirc = savePath+File.separator+crtdate;
          // 创建目录
             File uploadDir = new File(dirc);
             if (uploadDir.getParentFile() != null || !uploadDir.getParentFile().isDirectory()) {
                 //创建目录6
                uploadDir.getParentFile().mkdirs();
                if (!uploadDir.exists()) {
                    uploadDir.mkdir();
                }
             }
             
            String filename=request.getParameter("filename");
            String filesay=request.getParameter("filesay");
            PicModel picModel=new PicModel();
            picModel.setFilename(filename);
            picModel.setFilesay(filesay);
            String imgs="";
             //获取上传的文件集合
            Collection<Part> parts = request.getParts();
            for (Part part : parts) {
                //获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
                String header = part.getHeader("content-disposition");
                //获取文件名
               String fileName = getNewName(getFileName(header));
               //把文件写到指定路径
               if(!"".equals(fileName)){
                   //20170914/15465456564564.jgp
                   part.write(dirc+File.separator+fileName);
                  
                   imgs += ","+crtdate+File.separator+fileName;
               }
            }
          if(imgs.length()!=0)
          {
              imgs = imgs.substring(1);
          }
            picModel.setImgurls(imgs);
            
            //调用servie方法,插入数据库
        
          PrintWriter out = response.getWriter();
          out.println("上传成功");
          out.flush();
          out.close();
    
    
    

    相关文章

      网友评论

        本文标题:多种方式实现文件上传

        本文链接:https://www.haomeiwen.com/subject/wsujsxtx.html