javaweb 文件上传

注意事项

我们在文件上传的时候需要知道一下几个事项。
1.为了服务器的安全,上传的文件应该放在外界不能直接访问的文件夹下,比如我们可以放在WEB-INF目录下。
2.为了防止上传文件出现覆盖 现象,上传文件的文件名应该保持他的唯一性(时间戳、uuid、位运算……)。
3.要限制上传文件的最大值。
4.限制上传文件的类型,在确定完上传文件名之后,我们应该对文件的后缀名进行判断。

准备工作

我们在进行文件上传之前我们应该准备两个jar包,UUID是啥。
处理上传文件,我们一般是通过request.getInputStream()方法来进行 这样我会很麻烦。我们是用Apache,组件
commonsfileuploadhttps://mirrors.tuna.tsinghua.edu.cn/apache//commons/fileupload/binaries/commons-fileupload-1.4-bin.zip
他的核心以赖于commons-io组件https://mirror.bit.edu.cn/apache//commons/io/binaries/commons-io-2.8.0-bin.zip
UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是一种软件建构的标准。UUID是一个128比特的数值,这个数值可以通过一定的算法计算出来。为了提高效率,常用的UUID可缩短至16位。UUID用来识别属性类型,在所有空间和时间上被视为唯一的标识。

创建项目

这里创建项目的方式有多种,不论你使用那一种创建方式,创建完之后都先要进行这两个jar的导入。
javaweb 文件上传
要把所导入的jar同时导入我们的项目目录下。
javaweb 文件上传
接下来就是写jsp页面,这里需要注意的是我们创建的from表单提交方式必须是post,enctype="multipart/form-data"类型必须这样写,这样服务器端才能从过流进行获取。<input type="file" name="file1" >这里的name也是必须要写的,否则不能读取。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

<%--  get提交方式限制文件大小,文件大小只能为4kb左右--%>
<%--  post提交方式不限值文件大小--%>
<%--enctype="multipart/form-data" 表单类型这样是如果服务器端想获取数据就必须要通过流--%>
<%--这里必须加上这个 ${pageContext.request.contextPath}这是获取服务器路径的--%>
  <form action="${pageContext.request.contextPath}/upload.do" enctype="multipart/form-data" method="post"  >
    上传用户:<input type="text" name="username"><br>
    <input type="file" name="file1" ><br>
    <input type="file" name="file2"><br>
    <input type="submit">
  </form>

  </body>
</html>

Servlet

接下就是需要我们创建一个servlet,写好映射路径。
我们对表单进行一个判断,看其是否带有上传文件,如果不对就直接结束这个方法不往下走。

//第一步我们是先判断改表单是普通表单还是带有上床文件的表单
        if (!FileUpload.isMultipartContent(request)){
            return;//如果是普通的表单他就会true 否则false 此时这个程序就会终止 不在会往下执行
        }

创建上传文件的路径
这里上传文件的路径在WEB-INF目录下,这样比较安全,外界并不能直接访问WEB-INF文件。有一个判断是判断当前路径下是否存在文件夹,如果不存就创建一个。

//创建上传文件的保存的路径
        String upLoadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(upLoadPath);
        if (!uploadFile.exists()){
            uploadFile.mkdir();//如果不存在就创建一个
        }

同时我们还需要创建一个临时文件夹,来进行缓冲临时文件。

//临时文件创建,如果文件大小超过我们的预期值,我们会把他存放在临时文件中,过几天会自动删除
        String tem = this.getServletContext().getRealPath("/WEB-INF/tem");
        File file1 = new File(tem);
        if (!file1.exists()){
            file1.mkdir();//创建一个临时目录
        }

核心 代码

ServletFileUpload类负责处理上传文件的数据,并将表单中的每个输入项封装成Filetem对象中,使用其paseRequest(HttpServletRequest)方法可以将通过表单中每一个HTML标签提交的数据封装称一个Filetem对象,然后以List列表形式返回,使用改方法处理上文件简单易用。
ServletFileUpload类负责处理上传文件的数据,并将表单中的每个输入项封装成Filetem对象中,再使用ServletFileUpload对象解析请求时需DiskFileItemFactory对象,所以我们在需要进行解析工作前构造好DiskFileItemFactory对象,通过ServletFileUpload对象的构造方法后或setFileItemFactory()方法设置ServletUpLoad对象的fileItem。
对这些类了解完之后,核心步骤就三步,这里我们用了三个方法来写
1.创建DiskFileItemFactory,处理临时文件的上传路径或者大小的限制。

public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        diskFileItemFactory.setSizeThreshold(1024*1024);//文件缓冲区,超过这个缓冲区1M 会被存为临时文件
        diskFileItemFactory.setRepository(file);
        System.out.println("DiskFileItemFactor创建成功");
        return diskFileItemFactory;

    }

2获取ServletFileUpload ,监听文件的进度,设置文件的大小,这些是根据情况来的,不写也可以他会有默认值。

public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
        //监听文件上传进度
        servletFileUpload.setProgressListener(new ProgressListener() {
            @Override
            //l以读文件大小 l1文件大小
            public void update(long l, long l1, int i) {
                System.out.println("文件大小为:"+l+"\t"+l1);
            }
        });
        //处理乱码问题
        servletFileUpload.setHeaderEncoding("utf-8");
        //设置单个文件的上传最大值
        servletFileUpload.setFileSizeMax(1024*1024*20);
        //设置总共能上传文件的大小
        servletFileUpload.setSizeMax(1024*1024*50);

        return servletFileUpload;

    }

3.处理这些上传文件。主要是通过parseRequest()来获取FileItem,
这里需要进行传三个参数,ServletFileUpload,HttpServletRequest ,upLoadPath。在这里根据自己的需要来进行编写。

 public static String  uploadParseRequest(ServletFileUpload servletFileUpload, HttpServletRequest request, String upLoadPath) {
        String msg="文件上传";
        try {
            //把前端请求解析,封装成一个FileTem对象,从servletFileUpload中获取
            List<FileItem> fileItems = servletFileUpload.parseRequest(request);
            for (FileItem fileItem:fileItems) {
                //判断上传表单是普通表单还是带有文件的表单
                if (fileItem.isFormField()){
                    //获取表单控件名字
                    String fieldName = fileItem.getFieldName();
                    //处理中文乱码
                    String value = fileItem.getString("UTF-8");
                    System.out.println(fieldName+value);
                }else{//现在是带有文件的表单

                    //处理文件---------------------

                    //获取文件名
                    String name = fileItem.getName();
                    System.out.println(name);
                    //trim()去除前后空格 判断文件名是否合法
                    if (name.trim().equals("")||name==null){
                        continue;//如果不合发他就会直接返回 判断下以位
                    }
                    //获取上传文件名 从最后以个/的下为开始截取
                    String filename = name.substring(name.lastIndexOf("/") + 1);
                    System.out.println(filename);
                    //获取文件的后缀名 用户判断文件名是否合法
                    String fileExtName = name.substring(name.lastIndexOf(".") + 1);
                    System.out.println(fileExtName);
                    //   UUID.randomUUID()会生成一个唯一表示的通用码
                    String uuidPath= UUID.randomUUID().toString();

                    //文件地址---------------

                    //文件存放的真实路径
                    String realpath = upLoadPath + "/" + uuidPath;
                    File realPathFile = new File(realpath);
                    if (!realPathFile.exists()){
                        realPathFile.mkdir();
                    }

                    //文件传输------------ (这个传输过程是先读取本地输入流,再把本地文件上传到服务器上,输出流)

                    //获取文件上传输入的流
                    InputStream inputStream = fileItem.getInputStream();
                    //创建一个输出流
                    FileOutputStream fileOutputStream = new FileOutputStream(realpath + "/"+filename);
                    //创建一个缓冲区
                    byte[] bytes = new byte[1024 * 1024];
                    //判断是否读取完毕
                    int len=0;
                    while ((len=inputStream.read(bytes))>0){
                        fileOutputStream.write(bytes,0,len);
                    }
                    msg="文件上传成功";
                    inputStream.close();
                    fileOutputStream.close();
                    //上传成功清除临时文件
                    fileItem.delete();

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return msg;
    }

接下来就是写一些相应跳转

 request.setAttribute("msg",msg);
  request.getRequestDispatcher("info.jsp").forward(request,response);

上传完成之后我们需要在这个路径下来进行查找
javaweb 文件上传
这里我们可以看到他的文件名是uuid。
javaweb 文件上传
完整的servlet

package aw;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUpload;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

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.*;
import java.util.List;
import java.util.UUID;

@WebServlet(name = "FileuploadServlet",urlPatterns = {"/upload.do"})
public class FileuploadServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //第一步我们是先判断改表单是普通表单还是带有上床文件的表单
        if (!FileUpload.isMultipartContent(request)){
            return;//如果是普通的表单他就会true 否则false 此时这个程序就会终止 不在会往下执行
        }

        //创建上传文件的保存的路径
        String upLoadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
        File uploadFile = new File(upLoadPath);
        if (!uploadFile.exists()){
            uploadFile.mkdir();//如果不存在就创建一个
        }

        //临时文件创建,如果文件大小超过我们的预期值,我们会把他存放在临时文件中,过几天会自动删除
        String tem = this.getServletContext().getRealPath("/WEB-INF/tem");
        File file1 = new File(tem);
        if (!file1.exists()){
            file1.mkdir();//创建一个临时目录
        }
        //处理上传文件,我们一般是通过request.getInputStream()方法来进行 这样我会很麻烦
        //我们是用Apache,组件commons-fileupload,他的核心以赖于commons-io组件
        //1.创建DiskFileItemFactory对象,处理文件的上传路径或者大小的限制
        DiskFileItemFactory factory = getDiskFileItemFactory(file1);

        //2.获取ServletFileUpload
        ServletFileUpload servletFileUpload = getServletFileUpload(factory);
        System.out.println(servletFileUpload.getSizeMax()+"--------------");

        //3.处理上传文件
        String msg = uploadParseRequest(servletFileUpload, request, upLoadPath);
        request.setAttribute("msg",msg);
        request.getRequestDispatcher("info.jsp").forward(request,response);
    }


    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    public static DiskFileItemFactory getDiskFileItemFactory(File file) {
        DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
        diskFileItemFactory.setSizeThreshold(1024*1024);//文件缓冲区,超过这个缓冲区1M 会被存为临时文件
        diskFileItemFactory.setRepository(file);
        System.out.println("DiskFileItemFactor创建成功");
        return diskFileItemFactory;

    }


    public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
        ServletFileUpload servletFileUpload = new ServletFileUpload(factory);
        //监听文件上传进度
        servletFileUpload.setProgressListener(new ProgressListener() {
            @Override
            //l以读文件大小 l1文件大小
            public void update(long l, long l1, int i) {
                System.out.println("文件大小为:"+l+"\t"+l1);
            }
        });
        //处理乱码问题
        servletFileUpload.setHeaderEncoding("utf-8");
        //设置单个文件的上传最大值
        servletFileUpload.setFileSizeMax(1024*1024*20);
        //设置总共能上传文件的大小
        servletFileUpload.setSizeMax(1024*1024*50);

        return servletFileUpload;

    }

    public static String  uploadParseRequest(ServletFileUpload servletFileUpload, HttpServletRequest request, String upLoadPath) {
        String msg="文件上传";
        try {
            //把前端请求解析,封装成一个FileTem对象,从servletFileUpload中获取
            List<FileItem> fileItems = servletFileUpload.parseRequest(request);
            for (FileItem fileItem:fileItems) {
                //判断上传表单是普通表单还是带有文件的表单
                if (fileItem.isFormField()){
                    //获取表单控件名字
                    String fieldName = fileItem.getFieldName();
                    //处理中文乱码
                    String value = fileItem.getString("UTF-8");
                    System.out.println(fieldName+value);
                }else{//现在是带有文件的表单

                    //处理文件---------------------

                    //获取文件名
                    String name = fileItem.getName();
                    System.out.println(name);
                    //trim()去除前后空格 判断文件名是否合法
                    if (name.trim().equals("")||name==null){
                        continue;//如果不合发他就会直接返回 判断下以位
                    }
                    //获取上传文件名 从最后以个/的下为开始截取
                    String filename = name.substring(name.lastIndexOf("/") + 1);
                    System.out.println(filename);
                    //获取文件的后缀名 用户判断文件名是否合法
                    String fileExtName = name.substring(name.lastIndexOf(".") + 1);
                    System.out.println(fileExtName);
                    //   UUID.randomUUID()会生成一个唯一表示的通用码
                    String uuidPath= UUID.randomUUID().toString();

                    //文件地址---------------

                    //文件存放的真实路径
                    String realpath = upLoadPath + "/" + uuidPath;
                    File realPathFile = new File(realpath);
                    if (!realPathFile.exists()){
                        realPathFile.mkdir();
                    }

                    //文件传输------------

                    //获取文件上传输入的流
                    InputStream inputStream = fileItem.getInputStream();
                    //创建一个输出流
                    FileOutputStream fileOutputStream = new FileOutputStream(realpath + "/"+filename);
                    //创建一个缓冲区
                    byte[] bytes = new byte[1024 * 1024];
                    //判断是否读取完毕
                    int len=0;
                    while ((len=inputStream.read(bytes))>0){
                        fileOutputStream.write(bytes,0,len);
                    }
                    msg="文件上传成功";
                    inputStream.close();
                    fileOutputStream.close();
                    //上传成功清除临时文件
                    fileItem.delete();

                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return msg;
    }


}


上一篇:javaweb 文件下载和上传


下一篇:【ncnn android】算法移植(四)——ubuntu上搭建环境,测试