文件上传

文件上传

1.普通表单提交默认enctype="application/x-www-form-urlencoded";但是当表单中存在文件类型时,需要设置enctype="multipart/form-data",它不对字符进行编码,用于发送二进制的文件(即所有文件类型,如视频、图片、音乐、文档都可以用此类型entype);还有一种enctype="text/plain"用于发送纯文本内容。

2.表单请求方式必须为post。

3.接收时不能再用request.getParameter(),而是request.getInputStream()解析二进制流,得到ServletInputStream对象。

image

image
image
image
image

当我们使用request.getInput直接获取到的字节流,后续进行打印数据的时候。会自动加上许多表单,文件的属性和属性值,还有分隔符。上传的是纯文本文件时,打印出来还能看到清除文件内容。但当上传的是非文本文件的时候,自动加上的属性和属性值,会导致文件不能正常显示。这时候我们就需要解析request.getInpustream()。

FileUpload文件上传

FileUpload是apache的commons组件提供的上传组件,它最主要的工作就是帮我们解析request.getInpustream()。可以参考在线API文档:http://tool.oschina.net/apidocs/apidoc?api=commons-fileupload

使用fileUpload组件首先需要引入两个jar包

  • commons-fileUpload.jar
  • commons-io.jar

    image

fileUpload的核心类有DiskFileItemFactory、ServletFileUpload、FileItem。

使用fileUpload固定步骤:

  • 创建工厂类:DiskFileItemFactory factory=new DiskFileItemFactory();
  • 创建解析器:ServletFileUpload upload=new ServletFileUpload(factory);
  • 使用解析器解析request对象:List list=upload.parseRequest(request);

使用的基本思想:

  • commons-fileupload 可以解析请求, 得到一个 FileItem 对象组成的 List
  • commons-fileupload 把所有的请求信息都解析为 FileItem 对象, 无论是一个一般的文本域还是一个文件域.
  • 可以调用 FileItem 的 isFormField() 方法来判断是一个 表单域 或不是表单域(则是一个文件域)
  • 再来进一步获取信息

一个FileItem对象对应一个表单项。FileItem类有如下方法:

  • String getFieldName():获取表单项的name的属性值。
  • String getName():获取文件字段的文件名。如果是普通字段,则返回null
  • String getString():获取字段的内容。如果是普通字段,则是它的value值;如果是文件字段,则是文件内容。
  • String getContentType():获取上传的文件类型,例如text/plain、image。如果是普通字段,则返回null。
  • long getSize():获取字段内容的大小,单位是字节。
  • boolean isFormField():判断是否是普通表单字段,若是,返回true,否则返回false。
  • InputStream getInputStream():获得文件内容的输入流。如果是普通字段,则返回value值的输入流。

文件名中文乱码处理:

  • servletFileUpload.setHeaderEncoding("utf-8") 或 request.setCharacterEncoding("utf-8");

表单普通字段中文乱码处理:

  • new String(str.getBytes("iso-8859-1","utf-8"));

设置内存缓冲区的大小,默认为10KB:

  • diskFileItemFactory.setSizeThreshold(10241024);*

指定临时文件目录,如果单个文件的大小超过内存缓冲区,该文件将会临时缓存在此目录下:

  • diskFileItemFactory.setRepository(file);

设置单个文件大小限制,如果有某个文件超过此大小,将抛出FileUploadBase.FileSizeLimitExceededException

  • servletFileUpload.setFileSizeMax(1024102410);**

设置所有文件,也就是请求大小限制,如果文件总和超过此大小,将抛出FileUploadBase.SizeLimitExceededException

  • servletFileUpload.setSizeMax(1024102420);**

利用UUID生成伪随机字符串作为文件名避免重复:UUID.randomUUID().toString();

将文件写到硬盘上。写完之后,系统会自动将放在临时文件目录的该文件删除:

  • fileItem.write(new File(path,fileName));
image
<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    $Title$


文件名 文件:
File:
文本域:
文本域:
package com.kylin.servlet;

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 org.apache.commons.io.FileUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

@WebServlet("/uploadServlet")
public class UploadServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");

        DiskFileItemFactory factory = new DiskFileItemFactory();

        //设置当超过文件的大小,就将文件写入到一个临时文件中
        factory.setSizeThreshold(1024 * 500);
        File tempDirectory = new File("C:\\Data\\Log");
        factory.setRepository(tempDirectory);

        ServletFileUpload upload = new ServletFileUpload(factory);

//        //设置单个文件大小限制
//        upload.setFileSizeMax(1024*1024*10);
//        //设置所有文件总和大小限制
//        upload.setSizeMax(1024*1024*30);

        //解决上传文件名的中文乱码
        upload.setHeaderEncoding("UTF-8");
        try {
            //1.得到FileItem的集合items
            List items = upload.parseRequest(req);
            //2.遍历items 若是一个一般的表单域,打印信息
            for (FileItem item : items) {
                if (item.isFormField()) {
                    String name = item.getFieldName();
                    String value = item.getString("utf-8");//解决一般表单域的乱码问题

                    System.out.println(name + ": " + value);
                } else {
                    //若是文件域则把文件保存到指定的目录下,
                    String fieldName = item.getFieldName();
                    String fileName = item.getName();
                    String contentype = item.getContentType();
                    long sizeInBytes = item.getSize();

                    System.out.println(fieldName);
                    System.out.println(fileName);
                    System.out.println(contentype);
                    System.out.println(sizeInBytes);

               /*     InputStream in = item.getInputStream();
                    byte[] buffer = new byte[1024];
                    int len = 0;

                    fileName = "C:\\Data\\Log\\" + fileName;
                    System.out.println(fileName);

                    OutputStream out = new FileOutputStream(fileName);

                    while ((len = in.read(buffer)) != -1) {
                        out.write(buffer, 0, len);
                    }
                    out.close();
                    in.close();*/
                    String suffix = fileName.substring(fileName.lastIndexOf("."));//截取文件后缀名
                    String uuid = UUID.randomUUID().toString();//制造唯一文件名
                    FileUtils.copyInputStreamToFile(item.getInputStream(), new File("C:\\Data\\IDM\\Java学习\\" + uuid + suffix));
                }
            }
        } catch (FileUploadException e) {
            e.printStackTrace();
        }
    }
}

你可能感兴趣的:(文件上传)