Servlet-文件上传的代码实现

文件上传

对于文件上传,都不陌生,但是一写代码,博主感觉也很迷,因为文件上传的原理过程确实太复杂了,我们一般使用第三方提供的方法来实现。

鉴于原生的文件上传真的太难了,所以Apache提供了处理文件上传的jar包(按照以往的习惯,还是提供了Maven仓库的地址,需要者可以自己去下载)。

博主这里就直接使用Maven依赖了:

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.6</version>
</dependency>

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

首先,文件上传一定得需要表单页面吧,原生页面,别嫌弃low哈

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
    用户名:<input type="text" name="username"/><br>
    文件:<input type="file" name="fileName"/><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

上传文件的表单一定要注意,表单提交方式一定要是post方式,而且一定要设置enctype="multipart/form-data",否则会失败。

提供处理上传文件的Servlet:

package cn.ara.servlet;

import org.apache.commons.fileupload.FileItem;
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.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

public class FileServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //判断上传的表单是普通表单还是文件表单
        if (!ServletFileUpload.isMultipartContent(request)) {
            return;//是一个普通的表单
        }

        try {

            //创建上传文件的保存路径,直接放在WEB-INF路径下,安全,用户无法直接访问
            String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
            File uploadFile = new File(uploadPath);
            if (!uploadFile.exists()) {
                uploadFile.mkdir();//不存在该文件夹就创建
                //打印绝对路径
                System.out.println(uploadFile.getAbsolutePath());
            }

            //缓存 临时文件
            //临时路径 如果文件超出预定的大小 就将它放到一个临时的文件中 一段时间后自动删除
            String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp");
            File tempFile = new File(tempPath);
            if (!tempFile.exists()) {
                tempFile.mkdir();//不存在该文件夹就创建
                //打印绝对路径
                System.out.println(tempFile.getAbsolutePath());
            }

            //处理上传的文件,一般都需要通过流来获取,可以使用request. getInputStream(),原生态的文件上:传流获取,十分麻烦
            //我们一般都建议使用Apache的文件上传组件来实现,common-fileupload, 它需要依赖于commons- io组件

            /*

            在使用ServletFileUpload对象解析请求时需要DiskFileItemFactory对象。
            所以,我们需要在进行解析工作前构造DiskFileItemFactory对象,
            通过ServletFileUpload,对象的构造方法或setFileItemFactory()方法没置ServLetFileUpload对象的fileItemFactory属性。
            */


            //1.创建DiskFileItemFactory对象,处理文件上: 传路径或者大小限制的;
            DiskFileItemFactory factory = new DiskFileItemFactory();
            //通过这个工厂设置一个缓冲区,当上:传的文件大于这个缓冲区的时候,将他放到临时文件中;
            factory.setSizeThreshold(1024 * 1024); //缓存区大小为1M
            factory.setRepository(tempFile);//临时目录的保存目录,需要一个File

            //2.获取ServletFileUpload ServletFileUpload负责处理上传的文件数据,并将表单中每个输入项封装成一个FileItem对象
            ServletFileUpload upload = new ServletFileUpload(factory);

            //监听文件上传进度 可以参考实现文件上传时的进度条
            upload.setProgressListener(new ProgressListener() {
                @Override
                //pBytesRead:已经读取到的文件大朴
                //pContentLength :文件 大朴
                public void update(long pBytesRead, long pContentLength, int pItems) {
                    //总大小 pContentLength
                    //已上传大小 pBytesRead
                    System.out.println("已上传: " + (pBytesRead*100) /pContentLength + "%");
                }
            });
            //处理乱码问题
            upload.setHeaderEncoding("UTF-8");
            //1024=1kb*1024=1M*10=10M
            //设置单个文件的最大值
            upload.setFileSizeMax(1024 * 1024 * 10);
            //设置总共能够上传文件的大小            
            upload.setSizeMax(1024 * 1024 * 10);

            //3.处理上传的文件
            //解析前端请求,把表单中的每一个输入项封装成一个个的FileItem
            List<FileItem> fileItems = upload.parseRequest(request);

            //遍历单个FileItem
            for (FileItem fileItem : fileItems) {

                //判断输入项是一个普通输入项还是带文件的输入项
                if (fileItem.isFormField()) {
                    //是一个普通表单
                    String name = fileItem.getFieldName();
                    String value = fileItem.getString("UTF-8");
                    System.out.println(name + ":" + value);

                } else {
                    //是一个文件输入项

                    //============= 处理文件 开始 ===============
                    //获取上传的带路径的文件名
                    String uploadFileName = fileItem.getName();
                    //如果文件名为空或者文件名不合法 则舍弃这个输入项
                    if (uploadFileName == null || uploadFileName.trim().equals("")) {
                        continue;
                    }
                    //获得上传的文件名
                    String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1);
                    //获得文件的后缀名
                    String fileNameSuffix = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1);

                    System.out.println("文件信息[文件名:" + fileName + ", 文件类型:" + fileNameSuffix + "]");

                    //============= 处理文件 结束 ===============

                    //============= 存放地址 开始 ===============
                    //使用UUID保证文件夹名的唯一 一个文件对应一个UUID的文件夹
                    String uuidPath = UUID.randomUUID().toString();
                    String relPath = uploadPath + "/" + uuidPath;
                    File relPathFile = new File(relPath);
                    if (!relPathFile.exists()) {
                        relPathFile.mkdir();
                    }

                    //============= 存放地址 结束 ===============


                    //============= 文件传输 开始 ===============
                    //获取输入项中的流
                    InputStream inputStream = fileItem.getInputStream();

                    //创建一个输出流
                    FileOutputStream fileOutputStream = new FileOutputStream(relPath + "/" + fileName);

                    //缓冲区
                    byte[] buffer = new byte[1024 * 1024];

                    int len = 0;
                    while ((len = inputStream.read(buffer)) > 0) {
                        fileOutputStream.write(buffer, 0, len);
                    }

                    //============= 文件传输 结束 ===============

                    //关闭流
                    fileOutputStream.close();
                    inputStream.close();

                    //删除临时文件
                    fileItem.delete();
                }

            }

        } catch (FileUploadException e) {
            e.printStackTrace();
        }

        //响应客户端
        response.getWriter().write("OK!");

    }

}

配置好Servlet之后,提交就可以发现上传的文件被存放到控制台打印的地址了。

在这里插入图片描述
在这里插入图片描述
文件上传就实现成功了。


文件上传有几个注意点:

  • 为了保证上传文件的安全,上传的文件一般保存在外界无法直接访问的目录下。
  • 为了防止文件的重复,应该为上传的文件提供一个唯一的文件名。
  • 为了节省服务器的内存资源,上传的文件通常会限制大小。
  • 为了上传文件的合法性,一般会通过后缀名限制文件上传的类型。

一般实际操作就视实际情况而定,博主这里没有限制文件上传的类型,仅供参考。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值