java攻城狮程序员程序猿阵线联盟-汇总各类技术干货

多种方式实现文件上传

2017-09-15  本文已影响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();

上一篇 下一篇

猜你喜欢

热点阅读