图片的上传

一:需要的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

       
posted @ 2017-04-12 14:43  西瓜的小弟西西瓜  阅读(299)  评论(0编辑  收藏  举报