JavaWeb实现文件上传和下载

发布时间 2023-11-25 11:29:50作者: Xproer-松鼠

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

commons-fileupload-1.4.jar

commons-io-2.6.jar

上传表单的enctype属性
enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。

语法
<form enctype="value">
1
属性值
值 描述
application/x-www-form-urlencoded 在发送前编码所有字符(默认)
multipart/form-data 不对字符编码。在使用包含文件上传控件的表单时,必须使用该值。
text/plain 空格转换为 “+” 加号,但不对特殊字符编码。主要用于大量文本数据的传递
ServletFileUpload对象解析请求
ServletFileUpload类是Apache组件处理文件上传的核心高级类,通过使用parseRequest(HttpServletRequest)方法可以将HTML中每个表单提交的数据封装成个Fileltem对象,然后以List列表的形式返回。

ServletFileUpload类方法
序号 方法名称 方法描述
1 void setSizeMax (long sizeMax) 设置请求信息内容的最大允许字 节数
2 List parseRequest (HttpServletRequest request) 解析form表单提交的数据返回一个 Fileltem实例的集合
3 static final boolean isMultipartContent (HttpServlet Requestrequest) 判断请求提交的方式是否是“multi- part/form-data”类型
4 void setHeaderEncoding (String encoding) 设置转换时所使用的字符集编码
ServletFileUpload详细简绍

FileItem接口常用方法

序号 方法名称 方法描述
1 public boolean isFormField() 判断Fileltem对象所封装的数据类型,普通表单字段返 回true,文件表单字段返回false
2 public String getName () 获得文件字段中所上传的文件名,普通表单字段调用此 方法返回 null
3 public String getFieldName () 返回表单字段元素的name属性值
4 public void write (File file) 将Fileltem对象中保存的文件数据内容写入指定的文 件中
5 public String getString () 将Fileltem对象中保存的主体内容以一个字符串返回, 其有一个重载方法getString(String encoding),可指定 所采用的编码集
6 public long getSize() 返回单个上传文件的字节数
FileItemFactory 接口的常用方法

序号 方法名称 方法描述
1 public void setSizeThreshold (int sizeThreshold) 设置内存缓冲区的大小
2 pubic void setRepositoryPath (String path) 设置临时文件存放的目录
文件上传
① 表单数据提交方式:POST
② 表单提交数据的类型:<form ... enctype=multipart/form-data>...</form>
③ 表单中设置文件上传项:<input type="file" ... />

页面

<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>使用Commons-FileUpload组件实现文件上传</title>
</head>
<body>
<form action="${pageContext.request.contextPath}/FileUpload" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="userName">
<br>
<%-- 加上multiple属性实现一次上次多个文件--%>
选择文件:<input type="file" name="myFile" multiple>
<br>
<input type="submit" value="上传">

</form>
</body>
</html>


servlet页面

package file;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

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;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

/**
* @author: BRILIANT屠一乐
* @date: 2022/12/2 15:41
* @description:
*/

@WebServlet(description = "FileUpload", urlPatterns = {"/FileUpload"})
public class FileUpload extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html");
//enctype 属性是否是multipart/form-data
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
//获取输出流
PrintWriter writer = response.getWriter();
//上传者
String userName = "";
//上传的文件名,最后输出用
StringBuffer fileStr = new StringBuffer("");
try {
if (isMultipart) {
//创建工厂实例
FileItemFactory factory = new DiskFileItemFactory();
//ServletFileUp-load实例依赖于FileItemFactory工厂
ServletFileUpload upload = new ServletFileUpload(factory);
//解析表单字段 封装成一个FileItem实例的集合
List<FileItem> itemList = upload.parseRequest(request);
//迭代器
Iterator<FileItem> iterator = itemList.iterator();
while (iterator.hasNext()) {
//依次解析每一个FileItem实例,即表单
FileItem fileItem = iterator.next();
if (fileItem.isFormField()) {
//普通表单字段
//如果表单属性name的值的userName, 就获取这个表单字段的值
if (fileItem.getFieldName().equals("userName")) {
//getString方法:重载方法getString(String encoding),可指定所采用的编码集
userName = fileItem.getString("UTF-8");
}
} else {
//文件表单字段
// getName()获得文件字段中所上传的文件名,普通表单字段调用此方法返回 null
String fileUpName = fileItem.getName();//用户上传的文件名
File file = new File("E:\\idea_program\\Web\\file\\src\\main\\webapp\\temp\\" + fileUpName);//要保存到的文件
if (!file.exists()) {
// file.createNewFile();//一开始肯定是没有的,所以先创建出来
}
fileItem.write(file);//写入,保存到目标文件
fileStr.append(fileUpName + "、");
}
}
fileStr.replace(fileStr.lastIndexOf("、"), fileStr.length(), "");
writer.print("<script>alert('用户" + userName + "上传了文件" + fileStr + "')</script>");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

文件下载
jsp页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page isELIgnored="false" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>文件下载列表</h1>
<a href=" down.do? path=<%=getServletContext().getRealPath("1.png")%>">
QQ图片20220704200735.jpg
</a><br>
<a href=" down.do? path=<%=getServletContext().getRealPath("deity.rar")%>">
deity.rar
</a><br>
<a href=" down.do? path=<%=getServletContext().getRealPath("maggie.rar")%>">
maggie.rar
</a><br>
<a href=" down.do? path=<%=getServletContext().getRealPath("rvncsse.rar")%>">
rvncsse.rar
</a><br>
</body>
</html>

servlet页面

package sunyang; /**
* @author: BRILIANT屠一乐
* @date: 2022/12/3 19:39
* @description:
*/

import javax.servlet.*;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.*;

@WebServlet("/Download")
public class Download extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("下载");
System.out.println(request.getParameter("path"));
String path = new String(request.getServletContext().getRealPath("1.png").getBytes("iso-8859-1"));
File file = new File(path);
InputStream in = new FileInputStream(file);
//通过响应建立输出流
OutputStream os = response.getOutputStream();
response.addHeader("Content-Disposition", "attachment;filename=" + new String(file.getName().getBytes("gbk"), "iso-8859-1"));
response.addHeader("Content-Length", String.valueOf(file.length()));
response.setCharacterEncoding("utf-8");
//通知浏览器以下载的方式打开
response.setContentType("application/octet-stream");
int data = 0;
while ((data = in.read()) != -1) {
os.write(data);
}
os.close();
in.close();
}

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


博客迁移dca3eb4c-07fc-443b-b497-abaf1dcf935c

直接使用Servlet类和输入/输出流实现。与访问服务器文件不同的是,要实现文件的下载,不仅需要指定文件的路径,该需要在HTTP协议中设置两个响应消息头,如下

//设定接收程序处理数据的方式
Content-Disposition:attachment; filename =
//设定实体内容的MIME类型
Content-Type:application/x-msdownload

 

参考文章:http://blog.ncmem.com/wordpress/2023/11/25/javaweb%e5%ae%9e%e7%8e%b0%e6%96%87%e4%bb%b6%e4%b8%8a%e4%bc%a0%e5%92%8c%e4%b8%8b%e8%bd%bd/

欢迎入群一起讨论