文件的上传和下载
文件的上传
文件上传涉及前台页面的编写和后台服务器端代码的编写,前台发送文件,后台接收并保存文件,这才是一个完整的文件上传。
前台页面
做文件上传的时候,会有一个上传文件的界面,首先我们需要一个表单,并且表单的请求方式是POST;其次我们的form表单的entype必须设为"multipart/form-data",即entype="multipart/form-data"意思是设置表单的类型为文件上传表单。默认情况下这个表单的类型是application/x-www-form-urlencoded,不能用于文件的上传。只有使用了multipart/form-data才能完整地传递文件数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>upload</title>
</head>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
Name : <input type="text" name="usrname"><br>
File : <input type="file" name="afile"><br>
<button type="submit">upload</button>
</form>
</body>
</html>
后台实现
使用注解@MultipartConfig将一个Servlet标识为支持文件上传。Servlet将multipart/form-data的POST请求封装成Part,通过Part对上传文件进行操作。
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.MultipartConfig;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.Part;
import java.io.IOException;
@WebServlet("/upload")
@MultipartConfig
public class Upload extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("file uploading...");
req.setCharacterEncoding("UTF-8"); //设置编码
String name = req.getParameter("usrname");
Part part = req.getPart("afile");
String fileName = part.getSubmittedFileName(); //获取上传文件名称
String filePath = req.getServletContext().getRealPath("/");
part.write(filePath + '/' + fileName); // tomcat10 在filePath中已经自带'/'
System.out.println("saving : " + filePath + "/" + fileName);
}
}
文件的下载
文件下载,即将服务器上的资源下载(拷贝)到本地,我们可以通过两种方式下载。
超链接下载
当我们在HTML或JSP页面中使用a标签时,愿意是希望进行跳转,但当超链接遇到浏览器不识别的资源时会自动下载;当浏览器能够直接显示的资源,浏览器就会默认显示出来,比如txt、png、jpg等。当然我们也可以通过download属性规定浏览器进行下载,但有的浏览器不支持。
<!--默认下载-->
<!--当超链接遇到浏览器不识别的资源时,会自动下载-->
<a href="text.txt">超链接下载</a>
<!--指定download属性下载-->
<!-- 当超链接遇到浏览器识别的资源时,默认不会下载。通过download属性下载-->
<a href="text.txt" download="whatis.txt">超链接下载</a>
download属性可以不写任何信息,会自动使用默认文件名。如果设置了download属性的值,则使用设置的值作为文件名。当用户打开浏览器点击超链接,就会下载此文件。
后台实现下载
步骤
- 需要通过
resp.setContentType()方法设置Content-type头字段的值,为浏览器无法使用某种方式或激活某个程序来处理MIME类型,例如application/octet-stream或application/x-msdownload等 - 需要通过resp.setHeader方法设置
Content-Disposition头的值为attchment;filename=文件名3.读取文件,调用resp.getOutputStream方法向客户端写入附件内容。
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.*;
@WebServlet("/download")
public class Download extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("UTF-8"); //设置客户端编码
resp.setContentType("text/html;charset=UTF-8");//设置返回编码
String fileName = req.getParameter("target");//获取文件名
if (fileName == null || "".equals(fileName.trim())) //.trim去除首尾空格
{
resp.getWriter().write("fileName can't be null");
return;
}
String path = getServletContext().getRealPath("/");
File file = new File(path + fileName);
if (file.exists() && file.isFile())
{
resp.setContentType("application/octet-stream");//设置文件类型为浏览器无法识别
resp.setHeader("content-Disposition", "attchment;filename=" + fileName); //返回头中写如文件名
InputStream is = new FileInputStream(file);
ServletOutputStream os = resp.getOutputStream();
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1)
{
os.write(bytes, 0, len);
}
is.close();
os.close();
} else {
resp.getWriter().write("The file does not exists, please try again.");
}
}
}