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