Javaweb之实现文件上传+点击下载功能【奔跑吧!JAVA】

Javaweb之实现文件上传+点击下载功能

实现目标:

1、编写index.jsp,可以进行文件上传

2、上传成功后跳回index.jsp,并把上传的文件名显示在index.jsp中(用a标签显示)。

3、点击文件名,可下载文件


准备工具:

  • IntelliJ IDEA 2019.2.3 x64 

  • apache-tomcat-8.5.15  

  • JSP 标准标签库(JSTL)


首先,简单编写Index,jsp的上传页面

<%-- Created by IntelliJ IDEA. --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>upload && download</title>
  </head>
  <body>
  
  //enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。
  //不对字符编码。在使用包含文件上传控件的表单时,必须使用该值
  <form action="upload" method="post" enctype="multipart/form-data"> 
  
    <input type="file" name="file">
    
    <input type="submit" value="上传">
    
  </form>

  </body>
</html>


再来编写UploadServlet.java的实现上传的IO

package com.blb.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.*;
import java.nio.file.Path;

//支持二进制处理
@MultipartConfig
@WebServlet("/upload") //映射路径
public class UploadServlet extends HttpServlet {
    String path="d:/upload/";  //上传的路径 这里我设置的是d盘的upload文件夹下
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
        Part file = req.getPart("file");

        //获取提交的文件名
        String fileName = file.getSubmittedFileName();
        //获取文件的输入流
        InputStream inputStream = file.getInputStream();
        //获取的文件传到path路径
        FileOutputStream fileOutputStream = new FileOutputStream(path+fileName);
        byte[] data = new byte[1024];
        int len;
        while ((len=inputStream.read(data))!=-1){   // 表示从InputStream中读取一个数组的数据,如果返回-1 则表示数据读取完成了。
            fileOutputStream.write(data,0,len);
            //循环读取数据
        }
       inputStream.close();
      fileOutputStream.close();  //关闭IO流

    }
}

检查一下,没什么错误,试着看看效果

选择一个图片文件 


点击上传后


检查D:/upload下是否有这个文件

证明咱们这个逻辑没问题哈,已经能实现上传到指定路径了


接着实现上传成功后跳回index.jsp,并把上传的文件名显示在index.jsp中(用a标签显示)。

这里先导入一个jstl的jsp

一定要在WEB-INF下导入,然后右键jstl选择 as a libray


导入完成后在jsp头部加入一个引入标签,然后在主体里加入forEach遍历这个上传的文件list 显示在浏览器的页面上

<%-- Created by IntelliJ IDEA. --%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> //jstl引入标签
<html>
  <head>
    <title></title>
  </head>
  <body>
  <form action="upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit" value="上传">
  </form>

  <h1>文件列表</h1>
  <c:forEach items="${files}" var="file">
    <a href="download?file=${file}">${file}</a><br>  //上传文件的名字的显示在a标签内
  </c:forEach>
  </body>
</html>

接着写实现点击a标签下载上传后的文件的功能代码DownloadServlet.java

package com.blb.servlet;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.ws.Service;
import java.io.FileInputStream;
import java.io.IOException;

@MultipartConfig
@WebServlet("/download")
public class DownloadServlet  extends HttpServlet {
    String path="D:/";
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //要下载的文件名
        String file = req.getParameter("file");

        //取得文件输入流
        FileInputStream fileInputStream = new FileInputStream(path + file);
        

        //获得输出流
        ServletOutputStream outputStream = resp.getOutputStream();

        //将文件名转码
        String fileName = new String(file.getBytes(), "iso-8859-1");
        resp.setContentType("application/octet-stream");    //告诉浏览器我这是一个二进制文件
        resp.setHeader("Content-Disposition", "attachment;filename=" + fileName);   //告诉浏览器文件名是什么
        resp.setContentLength(fileInputStream.available());         //告诉浏览器文件的大小是多少

        //IO流写操作,向客户端写内容
        byte[] data = new byte[1024];
        int len;

        while ((len=fileInputStream.read(data))!=-1){
            outputStream.write(data, 0, len);
        }
        fileInputStream.close();
        outputStream.close();
    }
}

接着来试试效果

nice,基本的效果都已经实现了,但是还是要优化之处,比如:

1、阅读IOUtis,把读写操作进行封装起来方便调用

package com.blb.utils;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

public class IOUtils {

    /**
     * 输入输出流读取操作封装
     * @param inputStream
     * @param outputStream
     * @throws IOException
     */

    public static void readAndWriter(InputStream inputStream, OutputStream outputStream) throws IOException {
        byte[] data = new byte[1024];
        int len;
        while ((len=inputStream.read(data))!=-1){
            outputStream.write(data, 0, len);
        }
        inputStream.close();
        outputStream.close();
    }

    /**
     * 下载配置
     * @param resp
     * @param file
     * @param length
     * @throws UnsupportedEncodingException
     */
    public static void downloadConfig(HttpServletResponse resp, String file, int length) throws UnsupportedEncodingException {
        String fileName = new String(file.getBytes(), "iso-8859-1");
        resp.setContentType("application/octet-stream");
        resp.setContentLength(length);
        resp.setHeader("Content-Disposition", "attachment;filename=" + fileName );
    }
}

2、下载前先判断文件是否存在

在DownloadServlet里添加如下代码:

if (!file1.exists()) {
    req.setAttribute("msg", "文件不存在");
    req.getRequestDispatcher("index.jsp").forward(req, resp);
    return;
}     //判断文件是否存在

然后在index.jsp里加一个绑定数据${msg}实现传递

<h1>文件列表</h1>
${msg}
<c:forEach items="${files}" var="file">
  <a href="download?file=${file}">${file}</a><br>
</c:forEach>

3、服务器重启后,文件列表丢失问题

第一次进来时,文件列表不能正常显示问题


package com.blb.servlet;

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;

@WebServlet("/index")
public class IndexServlet extends HttpServlet {

//    String path = "D:/upload/";

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        File dir = new File("D:/upload/");
        String[] list = dir.list();
        //把存放文件名集合的list放到session作用域中
        req.getSession().setAttribute("files", list);
        resp.sendRedirect("index.jsp"); //重定向
    }
}

最后的最后,这个小项目到这里结束了,欢迎大家指正!!

【奔跑吧!JAVA】有奖征文火热进行中:https://bbs.huaweicloud.com/blogs/265241

(完)