javaWeb 文件上传及下载

发布时间 2023-11-27 09:59:40作者: Xproer-松鼠

前言
网络上最常用的就是文件的上传和下载,本文讲解基于org.apache.commons.fileupload包及org.apache.commons.io包实现文件上传;通过设置响应头属性并基于文件流方式实现文件下载。

一、文件上传
1、实现思路
文件上传是通过表单上传,因此首先需要判断表单中是否包含文件类型的标签,如果表单中没有文件类型的标签,表明该表单中不包含文件上传的功能,无需后续操作;否则,表明该表单中包含文件上传的功能,继续进行文件上传的后续操作。
//该方法判断表单中是否包含上传文件,返回true代表包含,否则代表不包含
ServletFileUpload.isMultipartContent(HttpServletRequest request)

在服务器中创建保存文件的文件夹,为了保证上传文件的安全性,建议将文件夹建在项目的WEB-INF目录,因为该目录下的文件,无法直接被用户访问,一定程度上保证了安全性。
创建ServletFileUpload对象,基于该对象实现用户上传文件。
//基于该构造方法,创建ServletFileUpload对象。
//FileItemFactory 是一个接口,DiskFileItemFactory类实现了该接口,
//该类用于对文件夹进行管理,如设置文件夹存储空间大小的阈值,默认阈值是1M。
public ServletFileUpload(FileItemFactory fileItemFactory);

基于ServletFileUpload对象获取表单中的每一个标签控件,通过判断标签的类型依次对该标签内容进行处理,如果是文件类型标签,则通过文件流的方式将文件上传到服务器。为了避免文件因重名而导致覆盖丢失,本文使用UUID类生成唯一的字符串,以该字符串命名文件夹,将上传的文件保存在该文件夹下。
2、实现代码
2.1 pom 依赖文件
<dependencies>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>

<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
</dependency>

<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>

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

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>


2.2 前端jsp代码
<html>
<body>
<h2>上传文件</h2>

<form action="${pageContext.request.contextPath}/upload.do" method="post" enctype="multipart/form-data">
<p>上传用户:<input type="text" name="username"></p>
<p>上传文件1:<input type="file" name="file1"></p>
<p>上传文件2:<input type="file" name="file2"></p>
<p>
<input type="submit" value="提交"> | <input type="reset" value="重置">
</p>
</form>
</body>
</html>


2.3 web.xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"
metadata-complete="true">
<servlet>
<servlet-name>FileServlet</servlet-name>
<servlet-class>com.sun.servlet.FileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileServlet</servlet-name>
<url-pattern>/upload.do</url-pattern>
</servlet-mapping>

</web-app>


2.4 后台代码
public class FileServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 判断表单是否带上传文件
if(!ServletFileUpload.isMultipartContent(req))
{
return;
}
//2. 创建上传文件保存在服务器中的目录,建议在WEB-INF路径下,可以一定程度上保证安全
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println("上传文件根目录:"+uploadPath);
File uploadFile = new File(uploadPath);
if (!uploadFile.exists())
{
uploadFile.mkdir();
}
//3. 创建磁盘文件库
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
//4. 获取servlet文件上传对象
ServletFileUpload fileUpload = new ServletFileUpload(diskFileItemFactory);
//4.1 监控上传进度
fileUpload.setProgressListener(new ProgressListener() {
public void update(long l, long l1, int i) {
System.out.println("文件总大小:"+l1+" 已上传:"+l);
}
});
//4.2 处理乱码问题
fileUpload.setHeaderEncoding("UTF-8");
//4.3 设置单个文件大小的最大值
fileUpload.setFileSizeMax(1024*1024*10);
//4.4 设置总共能上传的文件大小最大值
fileUpload.setSizeMax(1024*1024*10);
//5. 处理上传的文件
try {
//5.1 获取表单中的每一个控件
List<FileItem> fileItems = fileUpload.parseRequest(req);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {//当前控件为普通表单
String fieldName = fileItem.getFieldName();
String value = fileItem.getString("UTF-8");
System.out.println(fieldName + ":" + value);
} else//当前控件为带文件的表单
{
//5.2 获取文件路径
String uploadFileName = fileItem.getName();
//5.3 对获取的文件字符串路径进行处理
if (uploadFileName.trim().equals("") || uploadFileName == null)
continue;
//5.3.1 获取文件名
String fileName = uploadFileName.substring(0,uploadFileName.lastIndexOf("."));
System.out.println("文件信息:"+"[文件名:"+fileName]");
//5.4 生成唯一的字符串,标识文件名,保证文件不会因为重名和覆盖
UUID uuidName = UUID.randomUUID();
//5.5 为上传的文件创建一个唯一命名的文件夹
String realUploadPath = uploadPath + "//" + uuidName;
File realUploadFile = new File(realUploadPath);
if (!realUploadFile.exists())
realUploadFile.mkdir();
//5.6 将上传的文件保存到上面存储的唯一文件夹中
//5.6.1 获取上传文件的流
InputStream inputStream = fileItem.getInputStream();
//5.6.2 将文件流写出到指定服务器文件
FileOutputStream fos = new FileOutputStream(realUploadPath + "//" + uploadFileName);
byte[] buffer = new byte[1024 * 1024];
int len = 0;
while ((len = inputStream.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
inputStream.close();
fileItem.delete();//上传成功,清除临时文件
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
String msg="文件上传成功";
//请求转发
req.setAttribute("msg",msg);
req.getRequestDispatcher("info.jsp").forward(req,resp);
}
}


二、下载指定文件
通过设置响应头属性,实现文件下载。

resp.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(fileName));

后台代码。

public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1. 获取下载文件路径
ServletContext context = this.getServletContext();
String realPath = this.getServletContext().getRealPath("/WEB-INF/classes/1.jpeg");
//2. 获取下载文件名
String fileName = realPath.substring(realPath.lastIndexOf("\\")+1);
//3. 浏览器设置下载文件方法, URLEncoder.encode解决中文乱码
resp.setHeader("content-disposition","attachment;filename="+ URLEncoder.encode(fileName));
//4. 获取下载文件的输入流
FileInputStream in = new FileInputStream(realPath);
//5. 创建缓冲区
int len=0;
byte[] buffer =new byte[1024];
//6. 获取输出对象
ServletOutputStream out = resp.getOutputStream();
//7. 将缓冲区中的数据输出
while ((len=in.read(buffer))>0)
out.write(buffer,0,len);
in.close();
out.close();
}

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

 

参考文章:http://blog.ncmem.com/wordpress/2023/11/27/javaweb-%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%8f%8a%e4%b8%8b%e8%bd%bd/

欢迎入群一起讨论