JSP实现文件上传和文件下载

JSP实现文件上传和文件下载

目录

JSP实现文件上传和文件下载

1. 文件上传

1.2 核心逻辑

1.3 中文乱码和名字重复

2. 文件下载

2.2 核心逻辑

2.3 中文乱码处理

3. 通用 Servlet 实现文件上传下载


IDEA 环境配置:导入依赖 jar 包。

  • commons-fileupload-1.4.jar
  • commons-io-2.6.jar

1. 文件上传

本质就是将一台电脑中的文件根据网络协议通过 io 流传递到另一台电脑(服务器)上。
1.1 三要素

① 表单数据提交方式:POST
② 表单提交数据的类型:<form ... enctype=multipart/form-data>...</form>
③ 表单中设置文件上传项:<input type="file" ... />

1.2 核心逻辑

前台 JSP 展示页面:

<form action="${pageContext.request.contextPath}/upload" method="post" enctype="multipart/form-data">
    描述:<input type="text" name="desc"> <br>
    上传附件:<input type="file" name="file"> <br>
    <button type="submit">提交</button>
</form>

后台 Servlet 核心逻辑:

    // 1. 创建磁盘文件项工厂对象
    // 2. 创建核心解析对象
    ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
    // 解决文件名中文乱码问题
    servletFileUpload.setHeaderEncoding("utf-8");
    try {
        // 3. 解析上传请求,获取文件项(包含form 中的所有项)
        List<FileItem> fileItems = servletFileUpload.parseRequest(request);
        for (FileItem fileItem : fileItems) {
            // 判断 fileItem 是否是上传的文件
            if (fileItem.isFormField()) {
                // true:其他的 form 项
                // 获取字段名称 <input name="字段名称">
                System.out.println(fileItem.getFieldName());
                // 描述 text 的中文内容乱码问题
                System.out.println(fileItem.getString("utf-8"));
            } else {
                // false:上传的文件
                // 输入流读到内存
                BufferedInputStream bis = new BufferedInputStream(fileItem.getInputStream());
                // 输出流写到服务器 request.getServletContext().getRealPath("upload")
                //File dirPath = new File(request.getRealPath("upload"));
                File dirPath = new File(request.getServletContext().getRealPath("upload"));
                if (!dirPath.exists()) {
                    dirPath.mkdir();
                }
                // 文件名 = 当前时间毫秒值 + 用户名(不重复) + 文件名
                String path = dirPath + File.separator + System.currentTimeMillis() + "-" + fileItem.getName();
                System.out.println(path);
                BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
                byte[] bs = new byte[8*1024];
                int size;
                while ((size = bis.read(bs)) != -1) {
                    bos.write(bs, 0, size);
                }
                bos.close();
                bis.close();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

文件上传到服务器:

// 存储到数据库(id, fileName, filePath, description)
FileService fileService = new FileServiceImpl();
MyFile myFile = new MyFile();
myFile.setFileName(filename);
myFile.setFilePath(request.getContextPath() + File.separator + "upload" + File.separator + filename);
myFile.setDescription(description);
fileService.addFile(myFile);

文件上传核心 API:

ServletFileUpload 核心解析类
    parseRequest(HttpServletRequest request) 解析请求,并获取相关文件项
    setHeaderEncoding(String encoding) 解决中文文件名乱码
FileItem 文件项
	boolean isFormField() 返回为true,普通字段。返回为false,就是文件
	String getFieldName() 获取表单 name 字段 
	String getString(String encoding) 根据指定编码格式获取字段值,解决描述文本中文乱码 
	String getName() 获取上传文件名称 
	InputStream getInputStream() 获取上传文件对应的输入流

1.3 中文乱码和名字重复

文件名中文乱码

// 1. 创建磁盘文件项工厂对象
// 2. 创建核心解析对象
ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
// 解决文件名中文乱码问题
servletFileUpload.setHeaderEncoding("utf-8");

描述内中文乱码

// 判断 fileItem 是否是上传的文件
if (fileItem.isFormField()) {
    // true:其他的 form 项
    // 描述 text 的中文内容乱码问题
    System.out.println(fileItem.getString("utf-8"));
} else { ... }

文件名重复问题

// 文件名 = 当前时间毫秒值 + 用户名(不重复) + 文件名
String path = serverPath + File.separator + System.currentTimeMillis() + "-" + username + "-" + fileItem.getName();

2. 文件下载

本质就是将一台电脑(服务器)中的文件根据网络协议通过 io 流传递到另外一台电脑上。

前端:超链接携带文件名参数
设置媒体类型
设置下载窗口(内容特征)
IO读写(写-响应给浏览器)

2.2 核心逻辑

超链接携带文件名

<a href="${pageContext.request.contextPath}/download?fileName=${file.fileName}">下载</a>

设置媒体类型

// 1. 设置媒体类型 <- 获取下载文件的媒体类型
String fileName = request.getParameter("fileName");
String mimeType = request.getServletContext().getMimeType(fileName);
response.setContentType(mimeType);

设置下载窗口(内容特征)

String userAgent = request.getHeader("User-Agent");
String newFileName = userAgent.contains("Chrome") ? URLEncoder.encode(fileName, "utf-8") : base64EncodeFileName(fileName);
// 2. 设置下载窗口 -> Content-Disposition
response.setHeader("Content-Disposition", "attachment;filename=" + newFileName);

IO读写(写-响应给浏览器)

// 3. IO读写文件: 读出服务器文件,响应写入到浏览器
String path = request.getServletContext().getRealPath("upload") + File.separator + fileName;
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
byte[] bs = new byte[8*1024];
int size = -1;
while ((size = bis.read(bs)) != -1) {
    bos.write(bs, 0, size);
}
bis.close();
bos.close();

2.3 中文乱码处理

不同浏览器编码方式不同:对文件名进行编码时以谷歌为代表的是 utf-8,其他浏览器是 base64
根据浏览器在下载窗口前设置编码方式:

String userAgent = request.getHeader("User-Agent");
String newFileName = userAgent.contains("Chrome") ? URLEncoder.encode(fileName, "utf-8") : base64EncodeFileName(fileName);
response.setHeader("Content-Disposition", "attachment;filename=" + newFileName);

base64编码 API(固定写法) :

public String base64EncodeFileName(String fileName) {
    BASE64Encoder base64Encoder = new BASE64Encoder();
    try {
        return "=?UTF‐8?B?"
               + new String(base64Encoder.encode(fileName.getBytes("UTF-8")))
               + "?=";
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException(e);
    }
}

3. 通用 Servlet 实现文件上传下载

upload.jsp

<h2>文件上传</h2>
<form action="${pageContext.request.contextPath}/file?methodName=upload" method="post" enctype="multipart/form-data">
    描述:<input type="text" name="description" > <br> <br>
    上传文件:<input type="file" name="file"> <br> <br>
    <button type="submit">提交</button>
</form>

fileList.jsp

<h2>文件列表:</h2>
<table border="1px" cellpadding="5px" cellspacing="0px">
    <tr>
        <td>编号</td>
        <td>文件名</td>
        <td>文件描述</td>
        <td>操作</td>
    </tr>

    <c:forEach items="${fileList}" var="file">
        <tr>
            <td>${file.id}</td>
            <td>${file.fileName}</td>
            <td>${file.description}</td>
            <td>
                <a href="${pageContext.request.contextPath}/file?methodName=download&fileName=${file.fileName}">下载</a>
            </td>
        </tr>
    </c:forEach>
</table>

FileServlet.java

@WebServlet(name = "FileServlet", urlPatterns = "/file")
public class FileServlet extends BaseServlet {
    private FileService fileService = new FileServiceImpl();

    public String upload(HttpServletRequest request, HttpServletResponse response) {
        ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory());
        servletFileUpload.setHeaderEncoding("utf-8");
        String filename = null;
        String description = null;
        try {
            List<FileItem> fileItems = servletFileUpload.parseRequest(request);
            for (FileItem fileItem : fileItems) {
                if (fileItem.isFormField()) {
                    description = fileItem.getString("utf-8");
                } else {
                    File dirPath = new File(request.getServletContext().getRealPath("upload"));
                    if (!dirPath.exists()) {
                        dirPath.mkdir();
                    }
                    filename = System.currentTimeMillis() + "-" + fileItem.getName();
                    String path = dirPath + File.separator + filename;

                    // IO流处理
                    BufferedInputStream bis = new BufferedInputStream(fileItem.getInputStream());
                    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(path));
                    byte[] bs = new byte[8192];
                    int size = 0;
                    while ((size = bis.read(bs)) != -1) {
                        bos.write(bs, 0, size);
                    }
                    bos.close();
                    bis.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        FileService fileService = new FileServiceImpl();
        FileInfo newFile = new FileInfo();
        newFile.setFileName(filename);
        newFile.setFilePath(request.getContextPath() + File.separator + "upload" + File.separator + filename);
        newFile.setDescription(description);
        boolean result = false;
        try {
            result = fileService.addFile(newFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result ? "r:/file?methodName=fileList" : "/upload.jsp";
    }

    public String fileList(HttpServletRequest request, HttpServletResponse response) {
        try {
            List<FileInfo> fileList = fileService.selectAllFiles();
            request.setAttribute("fileList", fileList);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "/fileList.jsp";
    }

    public void download(HttpServletRequest request, HttpServletResponse response) {
        String fileName = request.getParameter("fileName");
        String mimeType = request.getServletContext().getMimeType(fileName);
        response.setContentType(mimeType);

        String userAgent = request.getHeader("User-Agent");
        try {
            String newFileName = userAgent.contains("Chrome") ? URLEncoder.encode(fileName, "utf-8") : base64EncodeFileName(fileName);
            response.setHeader("Content-Disposition", "attachment;filename=" + newFileName);
            String path = request.getServletContext().getRealPath("upload") + File.separator + fileName;
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(path));
            BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
            byte[] bs = new byte[8192];
            int size = -1;
            while ((size = bis.read(bs)) != -1) {
                bos.write(bs, 0, size);
            }
            bos.close();
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public String base64EncodeFileName(String fileName) {
        BASE64Encoder base64Encoder = new BASE64Encoder();
        try {
            return "=?UTF‐8?B?"
                    + new String(base64Encoder.encode(fileName.getBytes("UTF-8")))
                    + "?=";
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

通用 Servlet :

@WebServlet(name = "BaseServlet", urlPatterns = "/base")
public class BaseServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String methodName = request.getParameter("methodName");
        System.out.println(methodName);
        try {
            Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
            String returnValue = (String) Objects.requireNonNull(method).invoke(this, request, response);
            if (null != returnValue) {
                if (returnValue.lastIndexOf(":") != -1) {
                    String path = returnValue.split(":")[1];
                    if (returnValue.startsWith("r")) {
                        response.sendRedirect(request.getContextPath() + path);
                    } else if (returnValue.startsWith("f")) {
                        request.getRequestDispatcher(path).forward(request, response);
                    }
                } else {
                    request.getRequestDispatcher(returnValue).forward(request, response);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}

版权声明:本文为CSDN博主「不才Jerry」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/sinat_36184075/article/details/105958347

补充说明

1、解决文件名含中文时,无法下载或下载文件名中文乱码问题,一般使用:

  String filename = URLEncoder.encode(fileNameBuffer.toString(), "UTF-8");

2、通过按钮点击下载文件时,一般使用window.open(downloadUrl);

var exportUrl = rootPath + "score/export";
window.open(exportUrl);

3、Java使用poi导出数据到excel文件(单表或多表导出)
JavaWeb系统后台列表数据导出到excel文件(前端导出)_zgphacker2010的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值