Servlet实现文件上传

写个基本的前端form表单页面,用于选择文件上传。由于是上传文件,请求的差异就体现出来了。**上传文件只能使用post请求,并且需要设置enctype=“multipart/form-data”**表示这是一个包含文件的表单。

注意事项:文件上传表单采用编码方式multipart/form-data 与 正常url编码不同,getParameter方法不能使用 setCharacterEncoding 无法解决输入项乱码问题

<div>
    <form method="post" enctype="multipart/form-data" action="${pageContext.request.contextPath}/upload.do">
        <p>用户: <input type="text" name="user"></p>
        <p>文件1: <input type="file" name="file1"></p>
        <p>文件2: <input type="file" name="file2"></p>
        <input type="submit" value="提交">
        <input type="reset" value="重置">
    </form>
</div>

文件上传所需的核心API的Maven依赖

<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.2</version>
</dependency>
<dependency>
	<groupId>commons-fileupload</groupId>
	<artifactId>commons-fileupload</artifactId>
	<version>1.4</version>
</dependency>

完成文件上传需要三个API核心接口:

  1. DiskFileItemFactory磁盘文件工厂类:设置缓存大小以及临时文件保存位置。

    setDefaultCharset("utf-8")				设置编码格式
    setSizeThreshold(1024*1024)				设置内存缓冲大小为1mb
    setRepository(String path)				当文件大小超过内存缓冲区大小时存放的路径
    

    内存缓冲区:上传文件的内容优先保存在内存缓冲区中,当上传文件大小超过缓冲区大小,就会产生一个临时文件tmp类型文件(俗称垃圾文件)

    临时文件存放位置: 保存超过了内存缓冲区大小上传文件而产生临时文件

  2. ServletFileUpload文件上传核心类:该类通过磁盘文件工厂获取到上传文件的缓冲区、临时文件地址。

    setHeaderEncoding("utf-8");			设置编码
    
    setSizeMax(1024*1024*100);			限制单次请求能够上传的文件大小(单位字节)    100mb        
    
    setFileSizeMax(20*1024*1024);		限制单个文件大小		20mb
    
    isMultipartContent(request)			判断request请求中是否是enctype="multipart/form-data"类型
    
    parseRequest(request)				解析request请求中携带的数据(包括文件)
    

  1. FileItem文件项目类:parseRequest(request)解析后得到的是List< FileItem >线性表,request对象中所有的数据:输入的数据、上传文件… 都是一个个的FileItem

    isFormField();				表单的一个普通字段返回true,  文件返回false
    
    getFieldName();				获得当前字段的名字	  即前端input中的 name 参数
    
    getString("utf-8")			以utf-8编码形式加载name 参数的 数据
    
    getName();					获得上传文件名
    
    getInputStream()			获得上传文件内容输入流,这个流可能是临时文件也可能是缓冲区中的文件数据
    
    delete()					用于删除产生的临时文件
    
  • getName()方法是比较特殊的,对于不同的浏览器上传的文件路径是不同的,使用的谷歌浏览器上传时只由文件名 + 类型。其他的浏览器可能囊括文件的全路径。

  • 用户上传的文件也是五花八门的,可以限制用户上传文本的类型…

  • 用户上传的文件必须进行唯一命名,解决方法:时间戳、MD5、UUID…

在这里插入图片描述

package com;

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 javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.UUID;

public class FileServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1. 设置上传文件存放的路径
        File dir = new File("D:\\file\\upload");
        if(!dir.exists()){                             //该路径不存在就建立一个
            dir.mkdirs();
        }


        //2. 创建DiskFileItemFactory磁盘文件项工厂类,设置一些参数
        DiskFileItemFactory dfif = new DiskFileItemFactory();
        dfif.setDefaultCharset("utf-8");              //设置文件编码
        dfif.setSizeThreshold(1024*1024);             //设置内存临时缓冲区大小为1mb
        dfif.setRepository(dir);                      //当上传的文件大于临时临时缓冲区时存放的位置
		//临时文件目录 和 最终存放目录是同一个

        //3. 获取ServletFileUpload文件上传对象
        ServletFileUpload sf = new ServletFileUpload(dfif);
        sf.setHeaderEncoding("utf-8");
        //1k * 1024  * 100 = 100m                 设置能够上传的文件总大小
        sf.setSizeMax(1024*1024*100);
        //设置单个文件大小              20mb
        sf.setFileSizeMax(20*1024*1024);



        //4. 对上传的数据进行解析
        try {
            List<FileItem> list = sf.parseRequest(req);
            for (FileItem item : list) {
                item.isFormField();
                if(item.isFormField()){                     //表单中的非文件数据
                    String name = item.getFieldName();      
                    String value = item.getString("utf-8");
                    System.out.println(name + " : " + value);
                }
                else{
                    String name = item.getName();
                    System.out.println("上传的文件名: " + name);
                    if(name == null || name.equals("")){            //没有文件,跳掉
                        continue;
                    }
                    String FileType = name.substring(name.lastIndexOf(".") + 1);        //.xxx类型
                    String FileName = name.substring(0,name.lastIndexOf("."));          //Filename.xxx文件名
                    System.out.println("文件名: " + FileName + ", 文件类型: " + FileType);
                    String uuid = UUID.randomUUID().toString();             //UUID获取一串随机数
                    String realpath = dir + "/" + uuid;                    
                    File file = new File(realpath);                     
                    file.mkdir();                                           //为这个文件建立一个文件夹
                    BufferedInputStream bis = new BufferedInputStream(item.getInputStream());
                    BufferedOutputStream bos = new BufferedOutputStream(
                            new FileOutputStream(realpath + "/" + name));
                    byte[] buf = new byte[1024*1024];           //1KB * 1024 = 1MB
                    int len = 0;
                    while((len = bis.read(buf)) != -1){
                        bos.write(buf,0,len);
                        bos.flush();
                    }
                    bos.close();
                    bis.close();
                //    item.delete();                      //删除临时文件
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值