• 图片的上传


    一:需要的jar包

      commons—io.jar

      commons—fileupload.jar这个包对io有依赖

    二:上传三部曲

      相关类:

          工厂:DiskFileItemFactory

          解析器:ServletFileUpload

          表单项:FileItem

      1)创建工厂    

    DiskFileItemFactory factory = new DiskFileItemFactory ();

      2)创建解析器 

    ServletFileUpload  servletFileUpload = new ServletFileUpload(factory);

      3)使用解析器来解析request,得到FileItem集合

    List<FileItem> fileItem = servletFileUpload.parseRequest(request);

    三:源码

      
      1.jsp

    <%--
      Created by IntelliJ IDEA.
      User: YuWenHui
      Date: 2017/4/12 0012
      Time: 14:00
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <html>
    <head>
        <title>上传图片</title>
    </head>
    <body>
    <h1>上传1</h1>
    <form action="<c:url value='/FileUploadServlet'/>" method="post" enctype="multipart/form-data">
        用户名;<input type="text" name="username"/><br/>
        照 片:<input type="file" name="zhaoPian"/><br/>
        <input type="submit" value="上传"/>
    </form>
    </body>
    </html>

      2:配置文件

    servlet>
            <servlet-name>FileUploadServlet</servlet-name>
            <servlet-class>servlet.FileUploadServlet</servlet-class>
        </servlet>
        <servlet-mapping>
            <servlet-name>FileUploadServlet</servlet-name>
            <url-pattern>/FileUploadServlet</url-pattern>
        </servlet-mapping>

      3:servlet

    
    
    package servlet;

    import cn.itcast.commons.CommonUtils;
    import org.apache.commons.fileupload.FileItem;
    import org.apache.commons.fileupload.FileUploadException;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;

    import java.io.File;
    import java.io.IOException;
    import java.util.List;

    /**
    * Created by YuWenHui on 2017/4/12 0012.
    */
    public class FileUploadServletPlus extends javax.servlet.http.HttpServlet {
    protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
    request.setCharacterEncoding("utf-8");
    response.setContentType("text/html;charset=utf-8");
    // 得到工厂
    DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory();
    // 创建解析器
    ServletFileUpload servletFileUpload =new ServletFileUpload(diskFileItemFactory);
    // 得到FIleItem集合
    try {
    List<FileItem> fileItemList = servletFileUpload.parseRequest(request);
    FileItem fileItem1 = fileItemList.get(0);
    FileItem fileItem2 = fileItemList.get(1);
    // 演示普通表单项
    System.out.println("普通表单项:"+fileItem1.getFieldName()+":"+fileItem1.getString("utf-8"));
    // 演示文件表单项
    System.out.println("文件表单项目演示:");
    System.out.println("ContentType:"+fileItem2.getContentType());
    System.out.println("名称:"+fileItem2.getName());
    System.out.println("size:"+fileItem2.getSize());
    // 获取文件的绝对路径
    String rootPath = this.getServletContext().getRealPath("/WEN-INF/files/");
    String fileName = fileItem2.getName();
    // 处理文件上传绝对路径问题
    int index = fileName.lastIndexOf("\");
    if (index != -1){
    fileName = fileName.substring(index+1);
    }
    // 给文件名添加UUID来处理文件的同名问题
    String saveName = CommonUtils.uuid()+"_"+fileName;
    // 得到hashCode
    int hashCode = fileName.hashCode();
    // 将hashCode转换成16进制
    String hex = Integer.toHexString(hashCode);
    // 生成完整路径
    File dirFile = new File(rootPath,hex.charAt(0)+"/"+hex.charAt(1));
    // 创建目录链
    dirFile.mkdirs();
    // 创建目录文件
    File destFile = new File(dirFile,saveName);
    // 保存文件
    fileItem2.write(destFile);
    System.out.println("文件保存在:"+dirFile);
    System.out.println(rootPath);

    } catch (FileUploadException e) {
    throw new RuntimeException(e);
    } catch (Exception e) {
    throw new RuntimeException(e);
    }
    }

    protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {

    }
    }
     

     四:上传的细节

      1:文件必须保存到WEB-INF下

        目的是不让浏览器直接访问到,防止攻击

      2:关于文件名的问题

        1.个别浏览器上传的是完整路径,需要切割

          如:上传的是E:/JavaWeb/***.jpg,我们只需要***.jpg

    //获取文件名
    String filename = fileItem2.getName();
    //java里面/符号需要转义,如果没用则返回-1
    int index = fulename.lastIndexOf("\");
    if(index != -1){
        filename = filename.subString(index+1);
    }

        2.文件名乱码或者普通表单项中乱码

          request.setCharacterEnCoding("utf-8))是有效的,因为fileUpload内部会调用request.getCharacterEnCoding()

          servletFileUpload.setHeanderencoding("utf-8")优先级高

        3.文件同名问题

          使用UUID来为每个文件添加前缀,扩展名不能更改

          这里需要是tools.jar包,而tool.jar对commons-beanutils和commons-logging.jar两个包存在依赖

    filename = commonUtils.uuid()+"_"+filename;

       3:目录打散问题

          不能在一个目录下存放过多的文件,存放过多时,打开目录速度变慢,并不易读取

           *哈希打散:

              通过文件名称得到int值,即调用hashCode()

              将int值换成16进制,获取16进制的前两位用来生成目录,即生成2级目录

              

    //            获取文件的绝对路径
                String rootPath = this.getServletContext().getRealPath("/WEN-INF/files/");
                String fileName = fileItem2.getName();
    //            处理文件上传绝对路径问题
                int index = fileName.lastIndexOf("\");
                if (index != -1){
                    fileName = fileName.substring(index+1);
                }
    //            给文件名添加UUID来处理文件的同名问题
                String saveName = CommonUtils.uuid()+"_"+fileName;
    //            得到hashCode
                int hashCode = fileName.hashCode();
    //            将hashCode转换成16进制
                String hex = Integer.toHexString(hashCode);
    //            生成完整路径
                File dirFile = new File(rootPath,hex.charAt(0)+"/"+hex.charAt(1));
    //            创建目录链
                dirFile.mkdirs();
    //            创建目录文件
                File destFile = new File(dirFile,saveName);
    //            保存文件
                fileItem2.write(destFile);
                System.out.println("文件保存在:"+dirFile);
                System.out.println(rootPath);

       4:文件的大小限制

          单个文件的大小限制和整个请求的大小限制

      

         servletFileUpload.setFileSizeMax(2*1024*1024);//限制单个文件的大小为2M
            servletFileUpload.setSizeMax(4*1024*1024);//限制整个表单大小为4M

        必须在解析之前对文件或者表单进行限制,即servFileUpload.parseRequest(request);函数调用之前使用

        若超出大小parseRequest函数将抛出异常

        超大文件的上传:

          可能和对文件的大小进行限制的方法有冲突

          需要在DiskFileItemFactory()创建时添加2个参数,如

     DiskFileItemFactory diskFileItemFactory=new DiskFileItemFactory(20*1024,new File("E:/JavaWebSrc/FileUpload/"));

       5:上传不能是用BaseServlet

          当上传文件时,request.getParametere()方法的返回值永远为null

           
  • 相关阅读:
    coredns bug
    Android的Sepolicy
    漫谈fork
    ftrace总结
    Framebuffer
    .net core 5 发送windows10桌面通知
    test_app 测试环境搭建
    GitHub骚操作
    git基于某分支创建新分支
    mysql导入数据load data infile
  • 原文地址:https://www.cnblogs.com/yuwenhui/p/6699143.html
Copyright © 2020-2023  润新知